If I use the views-view-fields.html.twig template in my own theme then the whole content get escaped so that "<" will be <
and so on for other braces, quotes etc.
This makes the template pretty unusable. I have found in some places here discussions about double escaping and similar problems. But currently I do not have a clue about the status of this escaping theme in Drupal 8 overall and if a solution for this problem is already insight. But for now I would consider this nearly a major bug for the views implementation since the custom templates are one of the great and powerful features of the views module.
To get past this now the easy way I just put it like this turning TWIG autoescape off
{% autoescape false %}
{% for field in fields %}
{{ field.separator }}
{{ field.wrapper_prefix }}
{{ field.label_html }}
{{ field.content }}
{{ field.wrapper_suffix }}
{% endfor %}
{% endautoescape %}
Of course this might be surely not the way it is meant to be, but I could not find a clue where to fix this otherwise.
PS: If I use the views-view.html.twig template in my own theme, there is no such problem.
Beta phase evaluation
Issue category | Bug because field values are getting inccorectly escaped |
---|---|
Issue priority | Major because it's a bug |
Unfrozen changes | Unfrozen because its a bug. |
Prioritized changes | The main goal of this issue is resolving escaping | Disruption | Disruptive for core/contributed and custom modules/themes because it will require a BC break/deprecation/data model changes/an upgrade path/internal refactoring/widespread changes... (Which? Specify.) |
Comment | File | Size | Author |
---|---|---|---|
#86 | 2363423-86.patch | 12.95 KB | stefan.r |
#86 | interdiff-80-86.txt | 1.32 KB | stefan.r |
#83 | 2363423-80.patch | 13 KB | stefan.r |
#83 | interdiff-76-80.txt | 2.71 KB | stefan.r |
#76 | interdiff.txt | 1.55 KB | Manuel Garcia |
Comments
Comment #1
star-szrThanks for the report @stefan.korn!
Comment #2
Manuel Garcia CreditAttribution: Manuel Garcia commentedHere's what we were doing on #2348747: Convert theme_views_view_fields() to 100% Twig: remove the theme function, taken out so we can at least fix this one.
I've tested it briefly, stuff is still escaped, let's see what the bot thinks.
Comment #3
Manuel Garcia CreditAttribution: Manuel Garcia commentedOops, forgot one on the theme function.
Comment #4
star-szrLooks good, thanks @Manuel Garcia. Can we get some tests please to show things are getting properly escaped and not double escaped?
Edit: Importantly, we should have a test-only patch that fails without the patch here.
Comment #5
Manuel Garcia CreditAttribution: Manuel Garcia commentedSo forgive me if I'm mistaken, but if we don't remove the theme function (See comment 77 on #2348747: Convert theme_views_view_fields() to 100% Twig: remove the theme function), this patch then needs to be reworked, so that the sanitization takes place on the theme function instead. That way when you are not using the twig file, stuff still gets sanitized. Does that sound right?
Comment #6
star-szrYes that sounds right, two potential code paths: theme function and template.
Comment #7
Manuel Garcia CreditAttribution: Manuel Garcia commentedOK I've been doing some testing on this one, and in order for us to fix this bug we have to move the markup generation part out of
template_preprocess_views_view_fields
, so stuff like:has to be moved into the theme function, and also into the template file.
Otherwise, doing the sanitizing on the theme function will result in escaped html being printed.
How should we do this, on this issue, a new one, or on #2348747: Convert theme_views_view_fields() to 100% Twig: remove the theme function ?
Comment #8
star-szrIf it's necessary to fix the escaping then this issue seems appropriate :)
Comment #9
Manuel Garcia CreditAttribution: Manuel Garcia commentedComment #10
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer commentedSome progress on this.
I'm not sure how to handle sanitizing the content... before the patch, it was done on render() using sanitizeValue(). But now from the theme function not sure how to go about it. Any pointers?
Comment #11
star-szrThanks @Manuel Garcia, I don't have a thought yet for how to fix the theme function not escaping, but here's a small point.
This comment should be kept.
Comment #12
star-szrActually Drupal\views\Plugin\views\HandlerBase::sanitizeValue() is just a fancy wrapper for Xss and SafeMarkup functions, and in this case I think it's just sending the output to SafeMarkup::checkPlain().
Comment #14
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer commentedGood catch Cottser on the comment, restored it now in this patch.
I've done some testing by copying over the twig template into bartik, and if we keep the sanitization on
FieldPluginBase::render
, the field.content does NOT get double escaped - looks like we can keep it there. So this patch restores that change. Could use with double checking, I suppose.Comment #16
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer commentedThis should get rid of all those exceptions. Not sure what's going on with the failing test though.
Comment #18
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer commentedMore on fixing exceptions..
Comment #19
penyaskitoShould we use a template/inline template here instead?
If we add a todo, let's create an issue for that.
Comment #20
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer commentedThanks @penyaskito for the review!
We've already discussed it on IRC, but I'll answer here as well for people reading the issue.
Comment #21
penyaskitoLooks good to me, but still needs the test.
Comment #22
xjmOh, this is a nice improvement. This will also help us with #2502089: Remove SafeMarkup::set() in template_preprocess_views_view_table().
I think we should not just be checkPlain()ing the tag -- we should be validating it against an allowed and valid tags list. Maybe the best thing to do would be to instead compose the whole markup string without any early sanitization and then run it through
SafeMarkup::checkAdminXss()
.Also, is there any possibility of converting
$output
to a render array? Then we could either put it in#markup
(which would make it be XSS-filtered automatically) or use more explicit render array structure.Comment #23
star-szrAs for converting
$output
to a render array, if so it would need to be immediately rendered so probably not much point that I can see. Theme functions must return strings.Comment #24
xjm@Cottser, thanks! So I'd go with the first suggestion then: assemble the HTML string, then checkAdminXss() on the whole thing. And if someone wants to use tags that are not allowed in the admin list, they can do that in code rather than through the UI.
Comment #25
xjmMmm, just noticed that the template also uses the elements right there. What's the relationship between
$output
and the template? How can we ensure the template is fully sanitized for XSS? Maybe we should check against the admin tag list? checkPlain() is a wash if we're putting angle brackets around it.Comment #26
star-szr@xjm yep that's a good point. Anything output in the template that isn't SafeMarkup (or similar with the new things we are going to introduce like SafeString) will be escaped, but
script
escaped ==script
.This may be a "if you want to shoot yourself in the foot" case as long as Views only provides safe options for wrappers and doesn't provide a text input so you can enter whatever you want. Not sure.
Comment #27
ibnkhaldun CreditAttribution: ibnkhaldun commentedHi!
I'm newy at D8. So perhaps my comment is wrong. I'm reading twig documentation and found there are 2 filters to avoid double escaped strings:
Thus the sample you wrote should be wroten as
Or you can set the filter "|escape" only where you know you'l have a double-escaped string.
Hope it helps.
Oh! Sorry i was reading on double-escape and came here from a link. And my comment out of branche's target
Comment #28
prajaankit CreditAttribution: prajaankit commentedComment #29
rootworkComment #31
star-szrThe patch from #20 is still fine. @prajaankit in the future please leave a comment when uploading a new patch explaining what you're doing.
I'm going to see if I can rough in a test here.
Comment #32
star-szrIt's a start, anyway.
Comment #34
lauriiiComment #35
joelpittetBeta eval added.
Comment #36
joelpittetThis is such a nice clean up! And it has tests. I'd like to see some manual testing on this.
Steps:
Comment #37
joelpittetI'll pick this up tomorrow if nobody snags it before then.
Comment #38
davidhernandezI coped the template to Classy and check a simple View before and after. Screenshots attached.
I realized something. Is it appropriate that the "THIS FILE IS NOT USED AND IS HERE AS A STARTING POINT FOR CUSTOMIZATION ONLY." text is there as an html comment and not a Twig comment? That makes it visible in the markup.
Comment #39
joelpittet@davidhernandez re "THIS FILE IS NOT USED AND IS HERE AS A STARTING POINT FOR CUSTOMIZATION ONLY."
That's a bit of legacy porting, probably should be Twig but if we can get that twig template in, it shouldn't matter. Feel free to open up a follow-up if you want to remove it quickly. I'll RTBC it right away if you ping me.
Comment #40
joelpittetThanks for covering off #36.4 @davidhernandez
Comment #41
davidhernandezI guess that is actually 5, since I moved the template. I didn't check before and after without moving the template.
Comment #42
joelpittet@davidhernandez so that is "with the patch" test in #38?
Comment #43
davidhernandezThat is before and after the patch, but with the template moved to Classy in both cases. I did not try things as-is, leaving the template alone, which I assume is what you want for testing the changes to the theme function?
Comment #44
joelpittetThanks for the manual testing @davidhernandez!
I did some too, the scenario was to take the existing admin content, convert from table to unformatted list and join the last 3 columns inline with a
|
.Reason I did the testing this way is to make sure the changes that were outside the template didn't break the existing theme function in some way.
Before Patch
With theme function
With twig template
After Patch
With theme function
With twig template
Turns out there is a missing
|
between the first and second inline item after this patch is applied.You can see this in the screenshots after
Status: Published|
Comment #45
joelpittetThe good thing is that they are consistent between the output of the theme and twig template after the patch is applied., the bad thing is we lost the separator:S
Likely need to add that to the tests.
Comment #46
davidhernandezTo be clear, you are talking about losing the pipe,
|
, between "Published" and "Updated"?Comment #47
joelpittetYes
Comment #48
davidhernandez@joel, what do you use to get those markers on the screenshot?
Comment #49
joelpittetSkitch! https://evernote.com/skitch/
Comment #50
dorficus CreditAttribution: dorficus as a volunteer commentedI rerolled the patch to be a little more current.
There were conflicts, however all I really needed to do was clean the 3-4 lines of code that were causing the issue. They were found in views-view-fields.html.twig at around line 34
Comment #51
dorficus CreditAttribution: dorficus as a volunteer commentedI rerolled the patch to be a little more current.
There were conflicts, however all I really needed to do was clean the 3-4 lines of code that were causing the issue. They were found in views-view-fields.html.twig at around line 34
EDIT: i messed this one up. disregard
Comment #52
dorficus CreditAttribution: dorficus as a volunteer commentedReroll without the messup. My apologies.
Comment #53
dorficus CreditAttribution: dorficus as a volunteer commentedInterdiff fixing twig comment close
Comment #54
joelpittetOk so something was wrong with my install in my tests I think because I've had @dorficus and I redo a manual test without being able to reproduce that issue. Also I believe @davidhernandez also couldn't get that to show up like that either.
Here's the new manual testing for #53
Comment #55
alexpottDon't we need a test with and without this test theme installed?
$this->assertNoEscaped('<') is easier on the eye.
I think this test twig file should have a comment stating that it exists because by default the one provided by views is not used.
The calls to SafeMarkup::checkPlain() should just be htmlspecialchars() as their safeness is immediately lost through string concatenation.
Comment #56
dawehnerIMHO this line is pointless. We should no test that config API works as expected
Given that this is functional identical to views-view-fields.html.twig i'm curious whether you could just use a twig include here
Comment #57
dorficus CreditAttribution: dorficus as a volunteer commentedThere's an issue that has some theme functions on the chopping block so that test without a theme install was not added. I did change the `<` to `<` and added the commenting as requested. I also changed the SafeMarkup::checkPlain methods to htmlspecialchars() function.
EDIT: I didn't see your request before I pushed this patch. I'll take care of those others.
Comment #58
davidhernandezdorficus, can you post an interdiff?
Comment #59
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedHere is the interdiff between #53 and #57.
Comment #60
dorficus CreditAttribution: dorficus as a volunteer commented@davidhernandez I apologize for forgetting the interdiff. Thank you @manuelgarcia for posting it.
Comment #61
dorficus CreditAttribution: dorficus as a volunteer commentedChanged to include, removed redundant test, added test text to make sure we're using right template.
Comment #62
dorficus CreditAttribution: dorficus as a volunteer commentedHad a no-newline error due to new IDE. Sorry.
No interdiff due to just one file with one line added to end.
Comment #63
dorficus CreditAttribution: dorficus as a volunteer commentedAdded a test without the theme installed
Comment #66
joelpittetThis looks great! Only nitpicks:)
Don't need this extra space after the function start.
Periods at the end of sentences.
We actually want this space between the function and the ending class for coding standards.
One new line here can be removed.
The reason for this template is to override the theme function provided by views. And nit: don't need to capitalize views.
Wicked.
Comment #67
dorficus CreditAttribution: dorficus as a volunteer commentedHandling the code issues
Comment #68
dorficus CreditAttribution: dorficus as a volunteer commentedGlance over this one and let me know if I missed anything.
Comment #69
dorficus CreditAttribution: dorficus as a volunteer commentedChanged a comment that I missed in the previous one.
Comment #70
dorficus CreditAttribution: dorficus as a volunteer commentedSomehow I lost some words. I found them and they're back under control.
Comment #71
joelpittetThanks for fixing all the nits!
This looks great to me and the tests look great and if the views template changes then we don't have to duplicate them to this copied template.
Comment #72
alexpotthtmlspecialchars()
needs to be replaced withHtml::escape()
Comment #73
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedWorking on #72.
Comment #74
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedAddressing #72.
Comment #75
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedComment #76
Manuel Garcia CreditAttribution: Manuel Garcia at Appnovation commentedOops, Html::escape() only takes one string as an argument...
Comment #77
dawehnerIs it okay to not escape $field->label_suffix?
Comment #78
stefan.r CreditAttribution: stefan.r commentedHtml::escape()
replacements look goodsuperfluous s
Comment #79
alexpott@dawehner++
In fact what is label_suffix? It does not seem to ever exist.
Comment #80
alexpottAh it is introduced by the patch.
Why not just pass the boolean into the template? Setting the suffix outside means we need to escape. Whereas if the twig template and theme_views_view_fields handled it it'd be obvious it was safe.
Comment #82
davidhernandezI'm not seeing things am I? The isset is written twice. Was the second one suppose to be a !empty?
Comment #83
stefan.r CreditAttribution: stefan.r commentedComment #84
joelpittetFor twig coding standards we don't use types https://www.drupal.org/node/1823416#datatypes
Though I think we should update that rule for booleans because we do that type frequently. @Cottser thoughts?
Minor clean-up but this could be nicer written as
{{ field.has_label_colon ? ': ' }}
But also the space is on the wrong side of the colon.
Comment #85
alexpottDo you need the
isset()
now? I think not.Comment #86
stefan.r CreditAttribution: stefan.r commentedComment #87
star-szr@joelpittet/#84: yeah the special naming, not sure. I thought we had written up those conventions somewhere but maybe not.
Comment #88
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer commentedWell, if has to be themer friendly, how about:
"Whether or not to display a colon after the label."
Comment #91
joelpittet@Manuel Garcia it's not really about being "themer friendly" it's mostly because Twig treats arrays like objects in our their keys are accessed, from what I recall.
That could be a better change but I'd rather not hold up this blocker on a comment that isn't clearly documented.
Comment #92
alexpottCommitted e76a96f and pushed to 8.0.x. Thanks!
Comment #94
dawehnerNice work
Comment #95
sgalindo2388 CreditAttribution: sgalindo2388 commentedI tried this patch with Beta 14 and I get this error
"Fatal error: Call to undefined method Drupal\Component\Utility\Html::escape() in /core/modules/views/views.theme.inc on line 205"
Any ideas on what might be going on?
Comment #96
stefan.r CreditAttribution: stefan.r commented@sgalindo this will not work with beta14, you'll need to use HEAD instead
Comment #97
joelpittet@sgalindo2388 if you want to play with it that method was added in #2550945: Add Html::escape() But you'd be better off with HEAD like @stefan.r suggested.
Comment #98
sgalindo2388 CreditAttribution: sgalindo2388 commented@stefan.r @joelpittet Thank you for the suggestions. using HEAD worked.