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
| Comment | File | Size | Author |
|---|---|---|---|
| #25 | safemarkup_does_not-2504529-25.patch | 6.08 KB | joelpittet |
| #25 | interdiff.txt | 914 bytes | joelpittet |
| #24 | patch-filter-tips.png | 32.43 KB | dorficus |
| #24 | patch-code.png | 18.89 KB | dorficus |
| #24 | head-filter-tips.png | 39.43 KB | dorficus |
Comments
Comment #3
alexpottThis is a duplicate of #2547851: SafeMarkup::format() should require arguments without them it is just SafeMarkup::set() in disguise. Closing this one because the other issue has the complete fix.
Comment #4
catchActually closing.
Comment #5
alexpottThis issue now is a blocker for #2547851: SafeMarkup::format() should require arguments without them it is just SafeMarkup::set() in disguise
Comment #6
alexpottFrom @joelpittet missing some commas.
Comment #7
akalata commentedReviewing at MWDS
Comment #8
akalata commentedManually 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
Comment #9
joelpittetis implicit by
#markuprender array usingXss::filterAdminif the markup is not marked safe.@akalata will add screenshots.
Comment #10
alexpottIt'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.
Comment #11
akalata commentedAdding screenshots from my manual testing.
Comment #12
xjmYeah, now that #2550945: Add Html::escape() has consensus, let's update this to use that method. Thanks!
Comment #13
alexpottReplaced htmlspeciachars() with Html::escape().
Comment #14
dawehner'], 'class' => array('type')),
Nice, you are so used to [] now, you just cannot use it anymore :)
'], '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?
Comment #15
dawehnerComment #16
alexpott1. Fixed - we shouldn't be mixing formats.
2. Yep - nice spot :)
That'll teach me for going from postponed to rtbc.
Comment #19
joelpittetFixed the syntax error
Comment #20
joelpittetfiltered out the other htmlspecialchars in that test.
Comment #21
dorficus commentedReviewing
Comment #22
joelpittet@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.
Comment #23
alexpott$this->assertEscaped()?
Comment #24
dorficus commentedApplied cleanly and found no issues on filter/tips or on restricted html. Screencaps of head and patched code and UI.
Comment #25
joelpittetGood call @alexpott, re #23
Comment #26
joelpittetThis conflicts with #2547851: SafeMarkup::format() should require arguments without them it is just SafeMarkup::set() in disguise Whichever gets in first I'll re-roll the other one.
Comment #27
dorficus commentedReviewing
Comment #28
dorficus commentedLooks good. Ran the test just to be sure and it came back with 232 passes!
Good job, @joelpittet!
Comment #30
joelpittetRandom testbot failure. on \Drupal\system\Tests\Theme\FastTest
Comment #32
catchCommitted/pushed to 8.0.x, thanks!