8

I'm writing an app that uses Rails on the backend and javascript/backbone on the frontend. I'm trying to bootstrap some rails models into my javascript. Specifically, I'd like to load the contents of @courses into a js variable called window.courses. I've got the following in an html.erb file.

<%= javascript_tag do %>
    window.courses = JSON.parse('<%= @courses.to_json %>');
<% end %>

I'm expecting the erb preprocessor to render this into valid javascript, like so

<script type="text/javascript">
//<![CDATA[
    window.courses = JSON.parse('[{"code":"myCourseCode", ...
//]]>
</script>

... but, instead, I'm getting code that includes HTML entities.

<script type="text/javascript">
//<![CDATA[
    window.courses = JSON.parse('[{&quot;code&quot;:&quot;myCourseCode&quot;, ...
//]]>
</script>

Obviously, I get javascript errors when I try to parse this.

Does anyone know how I can deal with these HTML entities in order to produce valid javascript? I realize that one option would be to unescape the entities on the client side, but this seems like a roundabout solution. Is there a way that I can get Rails to produce JSON that doesn't need unescaping?

Community
  • 1
  • 1
dB'
  • 7,838
  • 15
  • 58
  • 101

2 Answers2

9

If you intend to use raw(obj.to_json) you MUST ensure the following is set.

ActiveSupport.escape_html_entities_in_json = true 
oreoshake
  • 4,712
  • 1
  • 31
  • 38
5

The question is solved by my comment, just for the record:

Rails escapes strings that are printed using <%= 'string' %>. By this, it is save to ouput user data. So, if you don't want Rails to escape the output, you have to tell Rails explicitly by using raw('string').

In your code, that would be: <%= raw(@courses.to_json) %>

Raul Pinto
  • 1,095
  • 8
  • 15
  • 1
    this is basically asking for xss. trivially. I've seen this hundreds of times, please don't ever use raw. – oreoshake Jan 23 '15 at 01:32
  • Thank you for your comment @oreoshake. Can you please point me a direction to an alternative? – Raul Pinto Jul 11 '16 at 07:56
  • In the answer above, I mention `ActiveSupport.escape_html_entities_in_json = true`. With that setting, and the default json backends, using <= @courses.to_json.html_safe %> is safe from xss. – oreoshake Jul 11 '16 at 18:29