Bogdan Gusiev's blog

How to make good software for people


JavaScript injection in JSON inserted directly into script tag
06 Apr 2011

Pass data from backend to javascript is done in many different ways. One of the most simple is to inject(<%= %>) value as function argument inside of script tag. Unfortunately this pattern has well known XSS vulnerability but in a little different form than same injection in html template.
<script type="text/javascript">
    App.initizalizeSomething(<%= data.to_json %>)
</script>
The reason is that browser treat </script> as close script tag no matter where is it inserted into script. So, the script tag can be closed unexpectedly and opened again with any code if the data argument will contain correctly formed sequence, like:
</script><script>alert('hello')</script>
Use #html_escape helper is wrong here because it has different type of escaping. For example you don't need to escape double quote in this case. Rails core team is aware of that problem and implemented special helper:
# A utility method for escaping HTML entities in JSON strings
# using \uXXXX JavaScript escape sequences for string literals:
#
#   json_escape('is a > 0 & a < 10?')
#   # => is a \u003E 0 \u0026 a \u003C 10?
#
# Note that after this operation is performed the output is not
# valid JSON. In particular double quotes are removed:
#
#   json_escape('{"name":"john","created_at":"2010-04-28T01:39:31Z","id":1}')
#   # => {name:john,created_at:2010-04-28T01:39:31Z,id:1}
#
# This method is also aliased as +j+, and available as a helper
# in Rails templates:
#
#   <%=j @person.to_json %>
#
def json_escape(s)
Implementation can be found in Rails source code.

javascript html xss escape json