Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
- Fresh D8 install
- Set site name to
<script>alert('test')</script>
- Notice how the site name is double-escaped.
Discovered at #2545972-91: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping.
Proposed resolution
Fix it.
Remaining tasks
TBD
User interface changes
None.
API changes
None.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#29 | Welcome_script.png | 122.39 KB | joelpittet |
#15 | interdiff.txt | 606 bytes | olli |
#15 | 2555503-15.patch | 2.93 KB | olli |
#12 | 2555503-12.patch | 2.33 KB | olli |
#7 | 255503-5.patch | 4.5 KB | stefan.r |
Comments
Comment #2
stefan.r CreditAttribution: stefan.r commentedFrom #2549791: Remove SafeMarkup::xssFilter() and provide ability to define #markup escaping strategy and what tags to filter -- what was the reason for the string cast?
Comment #3
Wim Leers#1: that's not the root cause of this though, because as #2545972-91: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping explains, the view's title is double escaped even in the preview of the view!
Comment #4
olli CreditAttribution: olli commentedIs this a proper fix for the preview?
Comment #5
olli CreditAttribution: olli commented#2/ #3: Can we remove the cast?
Comment #6
geertvd CreditAttribution: geertvd at XIO commentedIsn't the problem that the site name is already being escaped in
system.tokens.inc
Then the escaped site name gets replaced in
Welcome to [site:name]
and that string gets replaced later on again because it's never been marked as safe.For now I wrote some test coverage already to show the issue.
Comment #7
stefan.r CreditAttribution: stefan.r commentedThis patch points out some of the places where we try to touch the title... By no means final as it removes a whole bunch of XSS filtering (which it probably shouldn't), so I gues this will make a couple of tests fail as well.
As to the string cast and the early render of the welcome title, I suppose it was so we can get the head title in case it has tokens? Should a site title actually have markup anyway?
Comment #8
stefan.r CreditAttribution: stefan.r commentedComment #10
stefan.r CreditAttribution: stefan.r commented@olli yes, I suspect that cast should be gone because it marks the string as unsafe, so Twig escapes it again when it had already been filtered during the render call.
Maybe we could even somehow do away with the whole early render of the title as Twig can also deal with render arrays, just need to figure out what to do with the head title.
The views preview double escaping seems to be a separate problem, we try to filter the title multiple times before it arrives into the Twig template in ViewUI::renderPreview()
Comment #12
olli CreditAttribution: olli commentedHere's #5 + #6. Manually tested it by setting site name to
<script>alert('xss');</script>
with front page title set toWelcome to <em>[site:name]</em>
and it seems to work.Comment #13
olli CreditAttribution: olli commentedComment #14
stefan.r CreditAttribution: stefan.r commentedWhile this solves the double escaping on the frontpage view and the preview I wonder if this is the right fix? Just to echo @dawehner in #2531430: Page's <title> double escaped, in both cases the title has already been already escaped by the time we put it into the markup array, should it really be?
$executable->getTitle() has already been escaped here.
$variables['page']['#title']
has already been escaped here.This could also use a test for the double escaped title at
admin/structure/views/view/frontpage/preview/page_1
.Comment #15
olli CreditAttribution: olli commentedReverted a change from #2549791: Remove SafeMarkup::xssFilter() and provide ability to define #markup escaping strategy and what tags to filter:
Isn't the default still allowing admin tags so we can remove #allowed_tags?
#14
I don't see that. The replacement of [site:name] is escaped, but in #12 that
<em>..</em>
was not.Did another test by setting title in views ui to
Welcome to <del>[site:name]</del> <script>alert('xss2');</script>
with site name<script>alert('xss');</script>
. Now the getTitle() method returns a stringWelcome to <del><script>alert('xss');</script></del> alert('xss2');
:<script>alert('xss');</script>
is escaped,<script>alert('xss2');</script>
is filtered,<del>[site:name]</del>
is not escaped or filtered. So the title I see on front page, preview info area and preview title section looks like this: "Welcome to<script>alert('xss');</script>alert('xss2');".#14
I agree, and maybe use admin tags in that test.
EDIT: Replaced
<big>
with<del>
.Comment #16
olli CreditAttribution: olli commentedIn HEAD my manual test in #15 gives:
Front page:
Welcome to <script>alert('xss');</script> alert('xss2');
Preview info:
Welcome to <del><script>alert('xss');</script></del> alert('xss2');
Preview title section:
Welcome to
<script>alert('xss');</script>alert('xss2');Comment #17
stefan.r CreditAttribution: stefan.r commented@olli by escaped I meant filtered, I was testing with ampersands and the filtering escapes the
&
to&
:(So if my welcome message is
Welcome to [site:name] &
, that final ampersand will be set to&
already, because we've already filtered the string before we send the markup array into the rendering system, which I don't know is necessary.And as to the token replacement, why do we sanitize that, can't we just do that on output? Ie:
f
Comment #18
olli CreditAttribution: olli commentedNo, I don't think so. The default (sanitize=TRUE) is for rendering HTML so here we let system_tokens() know it needs to escape plain text data.
Comment #19
stefan.r CreditAttribution: stefan.r commentedYes the site name is clearly plain text so it should be escaped (on output), not filtered.
But then should the page title here be escaped or filtered, i.e. do we consider it plain text or HTML? In #2555931: Add #plain_text to escape text in render arrays there was a similar discussion, and it should actually probably be escaped / considered plain text as well as it's in line with what we do with node titles?
So then we could just have $this->view->getTitle() output the unsanitized title (including processed tokens) as '#plain_text', as opposed to as '#markup' -- and let the escaping happen there?
Comment #20
olli CreditAttribution: olli commented#19 Do you mean we'd drop support for html so something like
Revisions for <em>%1</em>
would not be possible in views title?Comment #21
stefan.r CreditAttribution: stefan.r commentedDo we do this in core? I've seen markup in titles on some drupal 7 sites (with sometimes unnecessary or double escaping elsewhere) but I'm unclear if we ever "officially" supported this?
Also, your use case seems clear and ability to use filters on all titles would be a nice to have, but do we need this on a Welcome message or a site name as well?
Comment #22
dawehnerI know that a lot of admin pages for example uses
<em>
tags in there, so I think allowing HTML for<h1>
is needed.For
<title>
I think stripping all tags is the right approach.Comment #23
Wim Leers#22++
Comment #24
stefan.r CreditAttribution: stefan.r commentedOK so maybe we allow a limited set of tags in
<h1>
titles, ie<em>
and<bdi>
, and strip all tags for<title>
?Comment #25
dawehnerWell this is the hard question, what should people be able to use in titles? I strong maybe also something which would make sense?
Comment #26
joelpittetAny chance we could just pass the string to #title without the render array? That will filter out tags. or maybe #plain_text is better suited here.
same here, just plain text?
Comment #29
joelpittetLooks like another issue solved this. Here's a screenshot using the steps to reproduce from the issue summary.