Repository navigation
Conversation
…her tag The scripting-events, form, doubleselect, optiontransferselect and xhtml tooltip templates wrapped the value of their on* (doubleOn*, doubleAccesskey) attributes in <#outputformat 'JavaScript'>. With FreeMarker 2.3.35 that output format escapes nothing and also turns off the HTML auto-escaping that applies to every other attribute, so a value such as x" autofocus onfocus="alert(1) closed the attribute and added new ones. The javatemplates engine already escapes these attributes. Drop the wrappers so the values go through the same auto-escaping as the rest of the attributes. Handlers containing ' & < > or " are now entity-encoded, which browsers decode before running the handler; the affected fixtures carry ' as &apache#39; and EventHandlerEscapeTest pins the escaped output under the simple, xhtml, css_xhtml and html5 themes.
lukaszlenart
left a comment
There was a problem hiding this comment.
Thanks, this looks right for the attribute handlers, and the fixture updates (' → ') plus EventHandlerEscapeTest cover them well. One change is needed before merging, plus one note.
-
xhtml/tooltip.ftlneeds JavaScript string escaping as well. Unlike the developer-writtenon*handlers, here the template itself places${attributes.tooltip}inside a JavaScript string literal:domTT_activate(this, event, 'content', '…'). With HTML escaping alone, a'in the tooltip text becomes'in the markup, but the browser decodes it before the handler runs, so the apostrophe still ends the string and the rest of the tooltip text runs as script on mouseover. Escaping the value for the string as well,${attributes.tooltip?js_string}(the HTML auto-escape then still applies on top), would keep the tooltip text a plain string. Could you add a test that renders a tooltip containing'and checks the result? Note thatdomTTinserts the content withinnerHTML, so markup in tooltip text still renders as markup. This change doesn't affect that. -
Behaviour change for the release notes.
',",&,<and>inon*values are now entity-encoded in the markup, and an application that escaped quotes in its handlers itself will now get double escaping. The PR description already explains this well. I'll carry it into the 7.5.0 notes.
… too
domTT_activate(this, event, 'content', '${attributes.tooltip}'...) places
the tooltip inside a single-quoted JS string literal. HTML-escaping alone
(the fix just applied to every other on* attribute) is not enough here: a
' in the tooltip survives the browser's attribute decoding and still ends
the JS string early, so the remaining tooltip text runs as script via
domTT's innerHTML insertion.
Apply ?js_string to the value before the existing HTML auto-escaping, so
the quote is backslash-escaped in the JS source and the HTML entity
encoding applies on top of that, same as Lukasz described on the PR.
EventHandlerEscapeTest gets a new case with an apostrophe followed by a
script tag in the tooltip text, confirming the string can't be broken out
of; the existing tooltip test's expectation is updated for the extra
backslash-escaping now present ahead of the entity encoding.
|
Added the JS-string escaping for |
…JS string context too
Same gap as the tooltip text itself: domTT_activate(this, event, 'content',
'...', 'delay', '${attributes.tooltipDelay}', 'styleClass',
'${attributes.tooltipCssClass}') places both values inside their own
single-quoted JS string literals nested in the onmouseover attribute.
Both are plain developer-settable String attributes (OGNL-evaluable via
findString(), same as tooltip), so a ' in either survives HTML-attribute
decoding and ends the JS string early, same innerHTML-reachable path.
Apply ?js_string to both, same as the tooltip value. New tests mirror
testJsTooltipApostropheCannotBreakOutOfTheJsString for each argument.
|
One more in the same spot: |
Fixes WW-5830
The
on*attributes (anddoubleOn*,doubleAccesskey) of the bundled FreeMarker templates are written inside<#outputformat 'JavaScript'>${...}</#outputformat>. These wrappers date from the WW-4972 work (3d20e80, 3549764); doubleselect got its own in WW-5240 (ac16896), the html5 theme copied them in WW-5444 (e24d2f2), and one more line was added to optiontransferselect in WW-5772 (a91460a). With FreeMarker 2.3.35 theJavaScriptoutput format escapes nothing and also switches off the HTML auto-escape that covers every other attribute, so these values are written raw. A handler value such asx" autofocus onfocus="alert(1)closes the attribute and adds new ones, while the same value intitleis escaped. The javatemplates engine already escapes these attributes, so the engines also differ.THREAT_MODEL §8.8 says a value a UI tag renders into an attribute is HTML-escaped "under every bundled theme and rendering engine", with only
escape/escapeHtmlBodyand URL-valued attributes excepted; §9 says a value the application hands to a framework tag is covered by §8.8.Change
Drop the
outputformatwrappers on exactly these attributes:simple/html5scripting-events.ftl,simple/html5formonsubmit/onreset(simple/form-common.ftl,html5/form.ftl),xhtml/form.ftlonreset,simple/doubleselect.ftl,simple/optiontransferselect.ftl(doubleOn*,doubleAccesskey, the buttononclick) and the JS tooltiponmouseoverinxhtml/tooltip.ftl. Nooutputformatremains undertemplate/.css_xhtmlincludes thesimple/xhtmltemplates and is covered.Compatibility
A handler containing
',&,<,>or"is now entity-encoded in the markup (alert('x')is writtenalert('x')). Browsers decode character references in attribute values before the handler runs, so legitimate handlers behave the same. An application that worked around the raw output by escaping quotes itself (e.g.onclick="alert("x")") would now be double-escaped.This closes the attribute breakout only. It does not make request data safe inside JavaScript code or strings in a handler (
'is decoded before the script runs); that remains the application's job. I found no default framework path that feeds request data to these attributes; exposure needs an application that binds data into one, e.g.onclick="%{#parameters.x}".Tests
EventHandlerEscapeTestrendersx" autofocus onfocus="alert(1)throughtextfield(simple,xhtml,css_xhtml,html5),form,doubleselect,optiontransferselectand the JS tooltip, and checks the escaped output, withtitleas the control andonclick="doIt();"still rendered as is. With the templates reverted 5 of its 6 tests fail (the sixth, the legitimate handler, passes both ways); with the change all 6 pass.17 existing expected-output fixtures (34 tests) carried
'inside anon*value and now carry', asRadio-6.txtdid in 54d3dd1. I checked every changed fixture line: the only difference is'to'.Full
coresuite on the rebased branch: 3631 run, 0 failures, 0 errors, 2 skipped.Also checked against a running Struts Boot app rendering
<@s.textfield onclick="%{payload}" title="%{payload}"/>with that payload in all four themes: before,onclick="x" autofocus onfocus="alert(1)"(breakout) next to an escapedtitle; after,onclick="x" autofocus onfocus="alert(1)", escaped liketitle.