Problem/Motivation
In Drupal 8 we enabled twig autoescape but we also created SafeMarkup::checkPlain() to escape text and then mark it as safe to ensure that Twig does not double escape it.
Proposed resolution
We should rely on Twig auto escape and completely remove SafeMarkup::checkPlain(). SafeMarkup::checkPlain() is dangerous because if the resulting string is modified in any way, for example nl2br(), the result will no longer be marked safe. In places where explicit escaping is needed, Html::escape() should be used.
User interface changes
None
API changes
Remove SafeMarkup::checkPlain() completely.
Data model changes
None
Beta phase evaluation
| Issue category | Bug because we have double escaping in HEAD because of incorrect SafeMarkup::checkPlain() usage |
|---|---|
| Issue priority | Major because SafeMarkup::checkPlain() is hard to use correctly and we should be using auto escape |
| Disruption | Disruptive but we have announced this on d.o see #2555473: Deprecate SafeMarkup::checkPlain() for Drupal 8.0.x |
| Comment | File | Size | Author |
|---|---|---|---|
| #37 | interdiff.txt | 6.25 KB | dawehner |
| #37 | 2569699-37.patch | 12.33 KB | dawehner |
| #33 | 2569699-33.patch | 12.09 KB | dawehner |
| #33 | interdiff.txt | 3.11 KB | dawehner |
| #29 | interdiff.txt | 1.28 KB | lauriii |
Comments
Comment #2
alexpottComment #3
dawehnerComment #4
alexpottComment #5
alexpottPostponing on #2545972: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping
Comment #6
alexpottComment #9
lauriiiThe patch looks good. So long SafeMarkup::checkPlain() \o/
Comment #10
alexpott@lauriii did you read the batch documentation in form.inc - did it make sense to you? In the previous both @dawehner and @xjm expressed concern over the docs.
Comment #11
lauriiiSorry I didn't see the comments on the previous issue. After reading it again I agree that it could be more clear and the wording could be changed to be better. Maybe if there is specific comments about there, we could copy the feedback here.
Comment #12
joelpittetIs there a 'result' key or is this 'results'?
Can we get away with not sanitizing it first?
Yes this sounds a bit contradictory. It's using item list but yet still needs to be manually escaped by the callback. Is this a JS issue maybe?
This sounds like if the title was using t('@place') in the title then it would double escape by the auto-escape.
Also nit: 80 chars
Why isn't it being auto-escaped automatically like the 'results'?
Just a note: !placeholder may not be around for long but for now this is safe to say.
Comment #13
joelpittetSome further feedback from @Wimleers:
#2545972-66: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping
#2545972-77: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping
and from @xjm #2545972-115: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping
and clarification on this followup by @alexpott #2545972-183: Remove all code usages SafeMarkup::checkPlain() and rely more on Twig autoescaping
I'll try to consolidate and copy the relevant notes here but they all relate to form.inc
Comment #14
imiksuComment #15
joelpittetDiscussing the batch API with @alexpott IRL. We may be able to check safe variables and escape "just before" sending to the JavaScript. Ideally we would do this in JavaScript but this may be a nice DX compromise and would be slightly easier if we get an idea on how to deal with safe strings in JS in the future.
Comment #16
imiksuI decided to not touch yet on sanitization part of code as I'm not familiar enough with batch API, but I worked on following comments in #12:
Confirmed that and changed
Took off the whole sentence
Nailed it
I couldn't find better rephrasing for this, so I decided to leave it as is for now
Comment #17
mr.baileysGoing to take a stab at moving this forward.
Comment #18
lauriiiJust posting that this issue will also block this issues current solution: #2559971: Make SafeMarkup::format() return a safe string object to remove reliance on a static, unpredictable safe list but its blocked by other issue too.
Comment #19
lauriiiComment #22
lauriiiReroll of the latest patch.
Comment #23
joelpittetSo discussed briefly with @alexpott over the weekend and to avoid explaining what the finished batch API callback should/shouldn't do to variables we should just check the SafeStringInterface and escape if not safe otherwise just before it's sent to JavaScript, similar to what twig autoescape does.
Ultimately JS wouldn't know of SafeStringInterface and escape it... but I think this is the best solution.
Same, avoid this and check and escape if unsafe.
Comment #24
joelpittet#23 is the same as #15
Comment #25
lauriiiTrying to address #23 :)
Comment #26
joelpittetHere's what I was proposing, hopefully it does the trick.
Comment #29
lauriiiThis should fix the tests
Comment #30
alexpottIs it time to add
SafeMarkup::escapeIfUnsafe()it seems we have quite a few issues that need this.Comment #31
novitsh commentedTested patch from #29. No issues found. RTBC?
Comment #32
imiksuCreated #2573913: Create SafeMarkup::escapeIfUnsafe() out from #30.
Comment #33
dawehnerRerolling the patch, added some documentation and working on the test coverage now.
Comment #34
lauriii80 chars. The patch looks good but I don't think Im really qualified to RTBC this so leaving to someone else..
Comment #35
alexpottI think we need to document that regardless of where the output ends up it will autoescape.
Comment #36
stefan.r commenteds/javascript/JavaScript/
+1
s/javascript/JavasScript/
s/javascript/JavaScript/
Yay!
We want the mesage to be always escaped, right?
s:
<br>:<br />:s:
<br>:<br />:+1, should we also document the escaping behavior here?
Comment #37
dawehnerThank you for all your reviews!
Well it will be, through the usage of the "@" placeholder.
Did earlier.
Upload the current batch.
Comment #38
stefan.r commentedHow about "Note: The following elements might contain user input:
- $batch['title']
- $batch['init_message']
- $batch['progress_message']
- $batch['error_message']
- $context['results']
- $context['messaeg']
If the passed in value is not a SafeStringInterface object (such as an object returned from a valid t() call), then this value will be escaped an the batch JavaScript will display it as escaped as well."
:(
Do we want to assert anything here or merely check that the drupalGet is successful?
Comment #41
alexpottAs much as I would love to remove SafeMarkup::checkPlain() - it is actually unnecessary to achieve the goal of removing the safe string list. We can just have it return an object the implements SafeStringInterface. See #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list for an implementation that also completely removes the setter and getter functions for the safe list.
Given the fact that the disruption of removing SafeMarkup::checkPlain() for existing contrib and custom modules and given the acceptable work around I think we should postpone removal until Drupal 9.
Comment #42
alexpottCan people who have contributed to this patch please comment on #2575615: Introduce HtmlEscapedText and remove SafeMarkup::setMultiple() and SafeMarkup::getAll() and remove the static safeStrings list so they can receive credit for their work - thanks.
Comment #43
novitsh commented@alexpott: Does that also count for reviewing?
Can this issue be closed?
Comment #44
alexpott@Novitsh we will remove
SafeMarkup::checkPlain()in Drupal 9 - we can do that on this issue.Comment #45
stefan.r commentedComment #46
novitsh commented@alexpott, @stefan.r ok for me.
Comment #47
catchDuplicate of #2579701: remove SafeMarkup class.