.../Drupal/filter/Plugin/Filter/FilterCaption.php | 7 +++-
.../lib/Drupal/filter/Tests/FilterUnitTest.php | 34 +++++++++++++-------
2 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterCaption.php b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterCaption.php
index b9d2bdd..48fb5e1 100644
--- a/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterCaption.php
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/Filter/FilterCaption.php
@@ -9,6 +9,7 @@
use Drupal\Component\Utility\String;
use Drupal\Component\Utility\Unicode;
+use Drupal\Component\Utility\Xss;
use Drupal\Core\Annotation\Translation;
use Drupal\filter\Annotation\Filter;
use Drupal\filter\Plugin\FilterBase;
@@ -44,6 +45,10 @@ public function process($text, $langcode, $cache, $cache_id) {
if ($node->hasAttribute('data-caption')) {
$caption = String::checkPlain($node->getAttribute('data-caption'));
$node->removeAttribute('data-caption');
+ // Sanitize caption: decode HTML encoding, limit allowed HTML tags.
+ $caption = String::decodeEntities($caption);
+ $caption = Xss::filter($caption);
+ // The caption must be non-empty.
if (Unicode::strlen($caption) === 0) {
$caption = NULL;
}
@@ -105,7 +110,7 @@ public function tips($long = FALSE) {
');
}
else {
- return t('You can caption images (data-caption="Text") and align images (data-align="center").');
+ return t('You can caption (data-caption="Text") and align images (data-align="center"), but also video, blockquotes, and so on.');
}
}
}
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php
index 1220e99..b644b10 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php
@@ -66,6 +66,28 @@ function testCaptionFilter() {
$expected = '';
$this->assertIdentical($expected, $test($input));
+ // HTML entities in the caption.
+ $input = '';
+ $expected = '';
+ $this->assertIdentical($expected, $test($input));
+
+ // HTML encoded as HTML entities in data-caption attribute.
+ $input = '';
+ $expected = '';
+ $this->assertIdentical($expected, $test($input));
+
+ // HTML (not encoded as HTML entities) in data-caption attribute, which is
+ // not allowed by the HTML spec, but may happen when people manually write
+ // HTML, so we explicitly support it.
+ $input = '';
+ $expected = '';
+ $this->assertIdentical($expected, $test($input));
+
+ // Security test: attempt an XSS.
+ $input = '';
+ $expected = '';
+ $this->assertIdentical($expected, $test($input));
+
// Only data-align attribute: all 3 allowed values.
$input = '';
$expected = '';
@@ -113,18 +135,6 @@ function testCaptionFilter() {
$expected = '';
$this->assertIdentical($expected, $test($input));
- // Security test: attempt to put HTML in the caption (which would be
- // undetected by filter_html because the HTML would be embedded within an
- // HTML attribute and then rendered within the caption by filter_caption!).
- $input = '';
- $expected = '';
- $this->assertIdentical($expected, $test($input));
-
- // HTML in the caption is disallowed, but HTML entities shouldn't be.
- $input = '';
- $expected = '';
- $this->assertIdentical($expected, $test($input));
-
// Finally, ensure that this also works on any other tag.
$input = '';
$expected = '';