New encoding function needed for template literal context (string literals)
veita opened this issue · 8 comments
Encode.forJavaScript
is intended to
Encode for a JavaScript string. It is safe for use in HTML script attributes (such as onclick), script blocks, JSON files, and JavaScript source. The caller MUST provide the surrounding quotation characters for the string.
However, the string
input = "hell`;alert(1);`o"
encoded with Encode.forJavaScript
produces the following output which allows for XSS.
<!DOCTYPE html>
<html>
<body>
<script>
// var data = `<%=Encode.forJavaScript(input)%>`;
var data = `hell`;alert(1);`o`;
</script>
</body>
</html>
Related: #14
I think RULE #3 of the original OWASP XSS Prevention Cheat Sheet
Except for alphanumeric characters, escape all characters less than 256 with the \xHH format [...]
would handle this case correctly.
Template literals are in the JavaScript standard since ECMAScript 2015 Language Specification 6th Edition, June 2015. See the link I've posted in my first comment above.
Jim, thank you very much.
-Alex
The above use case would be better handled by using strings instead of template literals. But I assume this is just mentioned as a demonstration, and that there is a valid use case for embedding server side data in a template literal. An easy way to do it right now would be to embed the server-side string in the template literal by surrounding it with ${"
and "}
and escaping it. Hopefully this can provide a useful crutch for now:
<!DOCTYPE html>
<html>
<body>
<script>
// var data = `${"<%=Encode.forJavaScript(input)%>"}`;
var data = `${"hell`;alert(1);`o"}`; // does not pop alert
</script>
</body>
</html>
My recommendation, however, would be to instead escape the content to a JavaScript variable, and then use a template literal that references the variable, e.g.:
var input = "<$= Encode.forJavaScript(input) $>";
var data = `Here's your input: ${ input }, hope it's not XSS!`;
After talking with @jeffi we decided to politely close this out and not add a new encoding method. I'll update the wiki to address this issue per Jeff's comments.
Would there really be the need to create a new encoding method?
From my naive point of view template literals are just a third kind of string literals delimited by backticks instead of single or double quotes.
So my guess is that it would suffice to let the existing Encode.forJavaScript
output \x60
for any occurrence of the backtick.