diff --git a/core/lib/Drupal/Component/Utility/SafeMarkup.php b/core/lib/Drupal/Component/Utility/SafeMarkup.php index b11a65a..3d4856b 100644 --- a/core/lib/Drupal/Component/Utility/SafeMarkup.php +++ b/core/lib/Drupal/Component/Utility/SafeMarkup.php @@ -154,23 +154,24 @@ public static function escape($string) { * @see \Drupal\Component\Utility\Xss::filterAdmin() */ public static function xssFilterAdmin($string) { - if (!static::isSafe($string)) { - $string = Xss::filterAdmin($string); - static::set($string); - } - return $string; + $string = Xss::filterAdmin($string); + return static::set($string); } /** - * Applies a very permissive XSS/HTML filter for admin-only use. + * Applies a very permissive XSS/HTML filter for admin-only use, if not safe. + * + * @param string $string + * A string. * - * @deprecated as of Drupal 8.0.x, will be removed before Drupal 9.0.0. Use - * \Drupal\Component\Utility\SafeMarkup::xssFilterAdmin() instead. + * @return string + * The escaped string. If $string was already set as safe with + * self::set(), it won't be escaped again. * * @see \Drupal\Component\Utility\SafeMarkup::xssFilterAdmin() */ public static function checkAdminXss($string) { - return static::xssFilterAdmin($string); + return static::isSafe($string) ? $string : static::xssFilterAdmin($string); } /** diff --git a/core/lib/Drupal/Core/Render/Element/HtmlTag.php b/core/lib/Drupal/Core/Render/Element/HtmlTag.php index c861cf5..f817c7f 100644 --- a/core/lib/Drupal/Core/Render/Element/HtmlTag.php +++ b/core/lib/Drupal/Core/Render/Element/HtmlTag.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Render\Element; use Drupal\Component\Utility\SafeMarkup; +use Drupal\Component\Utility\Xss; use Drupal\Core\Template\Attribute; /** @@ -161,7 +162,7 @@ public static function preRenderConditionalComments($element) { } else { // The IE expression might contain some user input data. - $expression = SafeMarkup::xssFilterAdmin($browsers['IE']); + $expression = Xss::filterAdmin($browsers['IE']); } // If the #prefix and #suffix properties are used, wrap them with @@ -173,8 +174,8 @@ public static function preRenderConditionalComments($element) { // Ensure what we are dealing with is safe. // This would be done later anyway in drupal_render(). - $prefix = isset($elements['#prefix']) ? SafeMarkup::xssFilterAdmin($elements['#prefix']) : ''; - $suffix = isset($elements['#suffix']) ? SafeMarkup::xssFilterAdmin($elements['#suffix']) : ''; + $prefix = isset($elements['#prefix']) ? Xss::FilterAdmin($elements['#prefix']) : ''; + $suffix = isset($elements['#suffix']) ? Xss::FilterAdmin($elements['#suffix']) : ''; // Now calling SafeMarkup::set is safe, because we ensured the // data coming in was at least admin escaped. diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index 6e56d0a..858501b 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -368,7 +368,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) { if (isset($elements['#markup'])) { // @todo Decide how to support non-HTML in the render API in // https://www.drupal.org/node/2501313. - $elements['#markup'] = SafeMarkup::xssFilterAdmin($elements['#markup']); + $elements['#markup'] = SafeMarkup::checkAdminXss($elements['#markup']); } // Assume that if #theme is set it represents an implemented hook. @@ -382,7 +382,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) { ); foreach ($markup_keys as $key) { if (!empty($elements[$key]) && is_scalar($elements[$key])) { - $elements[$key] = SafeMarkup::xssFilterAdmin($elements[$key]); + $elements[$key] = SafeMarkup::checkAdminXss($elements[$key]); } } } @@ -468,8 +468,8 @@ protected function doRender(&$elements, $is_root_call = FALSE) { // with how render cached output gets stored. This ensures that placeholder // replacement logic gets the same data to work with, no matter if #cache is // disabled, #cache is enabled, there is a cache hit or miss. - $prefix = isset($elements['#prefix']) ? SafeMarkup::xssFilterAdmin($elements['#prefix']) : ''; - $suffix = isset($elements['#suffix']) ? SafeMarkup::xssFilterAdmin($elements['#suffix']) : ''; + $prefix = isset($elements['#prefix']) ? SafeMarkup::checkAdminXss($elements['#prefix']) : ''; + $suffix = isset($elements['#suffix']) ? SafeMarkup::checkAdminXss($elements['#suffix']) : ''; $elements['#markup'] = $prefix . $elements['#children'] . $suffix; diff --git a/core/modules/aggregator/src/Controller/AggregatorController.php b/core/modules/aggregator/src/Controller/AggregatorController.php index eaa82e5..13ff3d9 100644 --- a/core/modules/aggregator/src/Controller/AggregatorController.php +++ b/core/modules/aggregator/src/Controller/AggregatorController.php @@ -7,7 +7,7 @@ namespace Drupal\aggregator\Controller; -use Drupal\Component\Utility\Xss; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Datetime\DateFormatter; use Drupal\aggregator\FeedInterface; @@ -187,7 +187,7 @@ public function pageLast() { * The feed label. */ public function feedTitle(FeedInterface $aggregator_feed) { - return Xss::filter($aggregator_feed->label()); + return SafeMarkup::xssFilter($aggregator_feed->label()); } } diff --git a/core/modules/dblog/src/Controller/DbLogController.php b/core/modules/dblog/src/Controller/DbLogController.php index 04be50a..b6d8326 100644 --- a/core/modules/dblog/src/Controller/DbLogController.php +++ b/core/modules/dblog/src/Controller/DbLogController.php @@ -207,7 +207,7 @@ public function overview() { $this->dateFormatter->format($dblog->timestamp, 'short'), $message, array('data' => $username), - Xss::filter($dblog->link), + SafeMarkup::xssFilter($dblog->link), ), // Attributes for table row. 'class' => array(Html::getClass('dblog-' . $dblog->type), $classes[$dblog->severity]), diff --git a/core/modules/menu_ui/src/Controller/MenuController.php b/core/modules/menu_ui/src/Controller/MenuController.php index 7287054..560bb18 100644 --- a/core/modules/menu_ui/src/Controller/MenuController.php +++ b/core/modules/menu_ui/src/Controller/MenuController.php @@ -7,7 +7,7 @@ namespace Drupal\menu_ui\Controller; -use Drupal\Component\Utility\Xss; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Menu\MenuParentFormSelectorInterface; use Drupal\system\MenuInterface; @@ -77,7 +77,7 @@ public function getParentOptions(Request $request) { * The menu label. */ public function menuTitle(MenuInterface $menu) { - return Xss::filter($menu->label()); + return SafeMarkup::xssFilter($menu->label()); } } diff --git a/core/modules/node/src/Controller/NodeController.php b/core/modules/node/src/Controller/NodeController.php index 5889912..b3732b9 100644 --- a/core/modules/node/src/Controller/NodeController.php +++ b/core/modules/node/src/Controller/NodeController.php @@ -8,7 +8,6 @@ namespace Drupal\node\Controller; use Drupal\Component\Utility\SafeMarkup; -use Drupal\Component\Utility\Xss; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Datetime\DateFormatter; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; @@ -195,7 +194,7 @@ public function revisionOverview(NodeInterface $node) { '#context' => [ 'date' => $link, 'username' => $this->renderer->render($username), - 'message' => Xss::filter($revision->revision_log->value), + 'message' => SafeMarkup::xssFilter($revision->revision_log->value), ], ], ]; diff --git a/core/modules/taxonomy/src/Controller/TaxonomyController.php b/core/modules/taxonomy/src/Controller/TaxonomyController.php index e24eb6f..2e35678 100644 --- a/core/modules/taxonomy/src/Controller/TaxonomyController.php +++ b/core/modules/taxonomy/src/Controller/TaxonomyController.php @@ -7,6 +7,7 @@ namespace Drupal\taxonomy\Controller; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Xss; use Drupal\Core\Controller\ControllerBase; use Drupal\taxonomy\TermInterface; @@ -54,7 +55,7 @@ public function addForm(VocabularyInterface $taxonomy_vocabulary) { * The term label. */ public function vocabularyTitle(VocabularyInterface $taxonomy_vocabulary) { - return Xss::filter($taxonomy_vocabulary->label()); + return SafeMarkup::xssFilter($taxonomy_vocabulary->label()); } /** @@ -67,7 +68,7 @@ public function vocabularyTitle(VocabularyInterface $taxonomy_vocabulary) { * The term label. */ public function termTitle(TermInterface $taxonomy_term) { - return Xss::filter($taxonomy_term->getName()); + return SafeMarkup::xssFilter($taxonomy_term->getName()); } } diff --git a/core/modules/user/src/Controller/UserController.php b/core/modules/user/src/Controller/UserController.php index dc669b2..19844f8 100644 --- a/core/modules/user/src/Controller/UserController.php +++ b/core/modules/user/src/Controller/UserController.php @@ -7,6 +7,7 @@ namespace Drupal\user\Controller; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Xss; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Datetime\DateFormatter; @@ -161,7 +162,7 @@ public function userPage() { * The user account name. */ public function userTitle(UserInterface $user = NULL) { - return $user ? Xss::filter($user->getUsername()) : ''; + return $user ? SafeMarkup::xssFilter($user->getUsername()) : ''; } /** diff --git a/core/modules/views/src/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php index 455f48e..386456c 100644 --- a/core/modules/views/src/Plugin/views/field/Field.php +++ b/core/modules/views/src/Plugin/views/field/Field.php @@ -671,7 +671,7 @@ public function renderItems($items) { if (!empty($items)) { $items = $this->prepareItemsByDelta($items); if ($this->options['multi_type'] == 'separator' || !$this->options['group_rows']) { - $separator = $this->options['multi_type'] == 'separator' ? SafeMarkup::xssFilterAdmin($this->options['separator']) : ''; + $separator = $this->options['multi_type'] == 'separator' ? SafeMarkup::checkAdminXss($this->options['separator']) : ''; $build = [ '#type' => 'inline_template', '#template' => '{{ items | safe_join(separator) }}', diff --git a/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php b/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php index 1776e75..5958ddf 100644 --- a/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/SafeMarkupTest.php @@ -213,6 +213,30 @@ public function testReplace($search, $replace, $subject, $expected, $is_safe) { } /** + * Tests the interaction between the safe list and XSS filtering. + * + * @covers ::xssFilter + * @covers ::xssFilterAdmin + * @covers ::checkAdminXss + */ + public function testAdminXss() { + // This will strip the tags. + $this->assertEquals('text', SafeMarkup::xssFilterAdmin('text')); + + // This won't will strip the tags and the string with html will be + // marked as safe. + $filtered = SafeMarkup::xssFilter('text', array('marquee')); + $this->assertEquals('text', $filtered); + + // This will strip the tags. + $this->assertEquals('text', SafeMarkup::xssFilterAdmin($filtered)); + $this->assertEquals('text', SafeMarkup::xssFilter($filtered)); + + // This won't will strip the tags. + $this->assertEquals('text', SafeMarkup::checkAdminXss($filtered)); + } + + /** * Data provider for testReplace(). * * @see testReplace()