how can untrusted values be included in a html-page as javascript string constants? Although the case i am asking uses JSF and Rails, I think this is a general problem independent of the server side framework.
on-attributes
It is obviously not enough to escape \ ' " in on-attributes:
onclick='alert("[variable]")'
variable: hello, world"); alert("XSS
result: alert("hello, world"); alert("XSS")
In Firefox this will show a "hello, world" and an "XSS" alert dialog. As the variable does not contain a ", the Rails function escape_javascript is not sufficient in this context. Appyling html escaping seems to be secure, as only the original dialog box is shown in this case:
result: onlick='alert("hello, world"); alert("XSS")'
script-tags
In <script> tags, however, different rules apply in Firefox:
<script type="text/javascript">
alert("hello, world"); alert("XSS");
</script>
This displays just one dialog box; but the quotes are displays in their escaped form. There are two conclusions: 1st) " is not parsed as an JavaScript quotation sign (good), 2nd) it is not parsed according to HTML rules either (bad). So that any attempt to html escape the constant creates broken data.
Skipping html escaping in script-tags, however, is not an option:
<script type="text/javascript">alert("[variable]");</script>
variable: hello, world</script><script>alert("XSS
result: <script type="text/javascript">
alert("hello, world</script><script>alert("XSS");</script>
The first script tag creates an syntax error because of the missing ". But in Firefox the injected second script tag is executed.
tl,dr
Is there a secure way to write untrusted values to JavaScript constants? This seems to be a total mess, and I am currently leaning towards using html elements (with style="dispaly:none") instead. An XMLHttpRequest call using JSON would be another option. But both approaches feel like cheating.