.../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 = '
“Loquacious llama!”
'; + $this->assertIdentical($expected, $test($input)); + + // HTML encoded as HTML entities in data-caption attribute. + $input = ''; + $expected = '
Loquacious llama!
'; + $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 = '
Loquacious llama!
'; + $this->assertIdentical($expected, $test($input)); + + // Security test: attempt an XSS. + $input = ''; + $expected = '
alert(\'Loquacious llama!\')
'; + $this->assertIdentical($expected, $test($input)); + // Only data-align attribute: all 3 allowed values. $input = ''; $expected = '
'; @@ -113,18 +135,6 @@ function testCaptionFilter() { $expected = '
Loquacious llama!
'; $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 = '
<em>Loquacious llama!</em>
'; - $this->assertIdentical($expected, $test($input)); - - // HTML in the caption is disallowed, but HTML entities shouldn't be. - $input = ''; - $expected = '
<Loquacious llama!>
'; - $this->assertIdentical($expected, $test($input)); - // Finally, ensure that this also works on any other tag. $input = '