Problem/Motivation

Found when working on #2488538: Add SafeMarkup::remove() to free memory from marked strings when they're printed.

 \Drupal\filter\Plugin\Filter\FilterHtml
// Paraphrased.
$tips[$tag][1] = '<a href="' . $base_url . '">' . SafeMarkup::checkPlain(\Drupal::config('system.site')->get('name')) . '</a>';

     array('data' => SafeMarkup::format('@var', array('@var' => $tips[$tag][1])), 'class' => array('type')),
          array('data' => SafeMarkup::format($tips[$tag][1]), 'class' => array('get'))

When you have two different formats configured to show the HTML formatting tips, the SafeMarkup calls run twice.

1, When $tips[$tag][1] is passed as @var, it's escaped and marked as safe.

2. When its passed to SafeMarkup::format() as the first argument, it's also marked as safe (unescaped).

3. When once again it's passed as @var, both the escaped and unescaped versions have both been marked as safe, so SafeMarkup doesn't bother to escape something it can see has already been escaped.

The problem is in this case that we actually want the 'double-escaping' here, because we're literally escaping the same string twice.

Proposed resolution

We need to remove SafeMarkup use from FilterHtml since the whole point of this page is print out both escaped and unescaped versions of the same html. Even better, our current test for this is proving that it is broken by testing for unescaped html between the code tags.

Remaining tasks

Determine whether there's a security issue here. If a string is marked as safe in one context, could it be unsafe in another? The approach taken mitigates all security concerns by falling back to the admin filter and all html that ends up on the page is actually contained in FilterHtml and there is nothing unsafe it that.

User interface changes

None.

API changes

None

Comments

Status: Needs review » Needs work

The last submitted patch, test_only_11.patch, failed testing.

The last submitted patch, test_only_11.patch, failed testing.

alexpott’s picture

catch’s picture

Status: Needs work » Closed (duplicate)

Actually closing.

alexpott’s picture

Title: SafeMarkup does not escape some filter tips (identical strings marked as safe for one context remain safe for other contexts) » SafeMarkup does not escape some filter tips - remove SafeMarkup usage from FilterHtml
Issue summary: View changes
Status: Closed (duplicate) » Needs review
StatusFileSize
new5.19 KB
alexpott’s picture

StatusFileSize
new1.3 KB
new5.19 KB

From @joelpittet missing some commas.

akalata’s picture

Reviewing at MWDS

akalata’s picture

Manually tested: both the "short" and "long" filter tips are rendered identically in HTML (and therefore appear visually identical). I would RTBC based on that, but would like some outside confirmation that

The approach taken mitigates all security concerns by falling back to the admin filter
joelpittet’s picture

Status: Needs review » Reviewed & tested by the community

The approach taken mitigates all security concerns by falling back to the admin filter

is implicit by #markup render array using Xss::filterAdmin if the markup is not marked safe.

@akalata will add screenshots.

alexpott’s picture

It'd be great to get #2550945: Add Html::escape() in first because we've now found a good reason why we want Html::encodeEntities() - PHP versions add new features that we might want to make use of.

akalata’s picture

Adding screenshots from my manual testing.

xjm’s picture

Status: Reviewed & tested by the community » Postponed

Yeah, now that #2550945: Add Html::escape() has consensus, let's update this to use that method. Thanks!

alexpott’s picture

Status: Postponed » Reviewed & tested by the community
StatusFileSize
new3.61 KB
new5.15 KB

Replaced htmlspeciachars() with Html::escape().

dawehner’s picture

  1. +++ b/core/modules/filter/src/Plugin/Filter/FilterHtml.php
    @@ -144,8 +144,12 @@ public function tips($long = FALSE) {
    +          array('data' => ['#prefix' => '<code>', '#markup' => Html::escape($tips[$tag][1]), '#suffix' => '

    '], 'class' => array('type')),

    Nice, you are so used to [] now, you just cannot use it anymore :)

  2. +++ b/core/modules/filter/src/Plugin/Filter/FilterHtml.php
    @@ -175,8 +179,12 @@ public function tips($long = FALSE) {
    +        array('data' => ['#prefix' => '<code>', '#markup' => Html::escape($entity[1]), '#suffix' => '

    '], 'class' => array('type')),

    +++ b/core/modules/filter/src/Tests/FilterAdminTest.php
    @@ -368,12 +368,15 @@ function testFilterTipHtmlEscape() {
    + $link = '' . htmlspecialchars($site_name_with_markup, ENT_QUOTES, 'UTF-8') . '';
    ...
    + $link_as_code = '' . htmlspecialchars($link, ENT_QUOTES, 'UTF-8') . '';
    + $ampersand_as_code = '' . htmlspecialchars($ampersand, ENT_QUOTES, 'UTF-8') . '';

    Should we use Html::escape() here as well?

dawehner’s picture

Status: Reviewed & tested by the community » Needs work
alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new3.17 KB
new5.55 KB

1. Fixed - we shouldn't be mixing formats.
2. Yep - nice spot :)
That'll teach me for going from postponed to rtbc.

The last submitted patch, 13: 2504529.13.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 16: 2504529.15.patch, failed testing.

joelpittet’s picture

Status: Needs work » Needs review
StatusFileSize
new5.56 KB
new1.28 KB

Fixed the syntax error

joelpittet’s picture

StatusFileSize
new983 bytes
new5.54 KB

filtered out the other htmlspecialchars in that test.

dorficus’s picture

Reviewing

joelpittet’s picture

StatusFileSize
new1.14 KB
new6.09 KB

@Dorf found that we had still SafeMarkup being used in the test, instead of opening another issue for that, I think we can remove it here too.

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/modules/filter/src/Tests/FilterAdminTest.php
@@ -312,7 +312,7 @@ function testFilterAdmin() {
-    $this->assertText(SafeMarkup::checkPlain($text), 'The "Plain text" text format escapes all HTML tags.');
+    $this->assertText(Html::escape($text), 'The "Plain text" text format escapes all HTML tags.');

$this->assertEscaped()?

dorficus’s picture

StatusFileSize
new22.24 KB
new39.43 KB
new18.89 KB
new32.43 KB

Applied cleanly and found no issues on filter/tips or on restricted html. Screencaps of head and patched code and UI.

joelpittet’s picture

Status: Needs work » Needs review
StatusFileSize
new914 bytes
new6.08 KB

Good call @alexpott, re #23

joelpittet’s picture

dorficus’s picture

Reviewing

dorficus’s picture

Status: Needs review » Reviewed & tested by the community

Looks good. Ran the test just to be sure and it came back with 232 passes!

Good job, @joelpittet!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 25: safemarkup_does_not-2504529-25.patch, failed testing.

joelpittet’s picture

Status: Needs work » Reviewed & tested by the community

Random testbot failure. on \Drupal\system\Tests\Theme\FastTest

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

  • catch committed 79bb881 on 8.0.x
    Issue #2504529 by joelpittet, alexpott, catch: SafeMarkup does not...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.