1

I am rendering a .js.erb file within my rails app. Within this file, I'm updating the options for a select box.

The most important thing is that I am doing this in a XSS Safe manner. Given the solution of this SO Post, which references OWASP DOM based XSS Prevention Cheat Sheet, I am updating the select box options the following way:

Attempt 1

// app/views/blogs/blogs_select_listing.js.erb

// remove all options
$('#blog_select_box').children().remove();

// iterate through @blogs collection, append each blog item as an option to select box
<% @blogs.each do |blog| %>
  var opt = document.createElement("option");
  opt.setAttribute("value", "<%= blog.id %>");
  opt.textContent = "<%= blog.name %>";
  $('#blog_select_box').append(opt);
<% end %>
  • Issue: the display text of blog.name is being html encoded. So for example, the text of "Johnson & Johnson" is instead being displayed as: "Johnson &amp; Johnson". Other special characters like apostrophes will have the same display issue.

Attempt 2

I am aware of the rails method html_safe, so I tried that: I updated "<%= blog.name %>"; to "<%= blog.name.html_safe %>";.

  • Issue: When I test for XSS via having blog.name be something like alert("Gotcha");, it breaks: The options are not updated at all. Ultimately it seems that the issue is that using html_safe in this context, the app doesn't know how to handle double quotes.

Atempt 3

This seems to work. It updates the options, the display text works, and the option with display text alert("gotcha"); simply displays as text and it doesn't execute as code:

// app/views/blogs/blogs_select_listing.js.erb

// remove all options
$('#blog_select_box').children().remove();

// iterate through @blogs collection, append each blog item as an option to select box
$('#blog_select_box')
.html("<%= j options_from_collection_for_select(@blogs, :id, :name) %>");
  • Issue: I'm uncertain if this is safe. I am uncertain because I ran across this article which expresses that j, which is an alias for escape_javascript is unsafe.

It is currently unclear how I can update select options from a .js.erb template which is both XSS safe and properly displays the text.

Neil
  • 4,578
  • 14
  • 70
  • 155

1 Answers1

1

Try to give my understanding:

  • To Attempt 1

Though you could Unescape special characters, but it's not the Rails way.

  • To Attempt 2

html_safe is not the method that can ensure you the string result is safe, but rather you clarify the string is safe, this way html tag within the string could be display as HTML, so it doesn't resolve XSS.

string = '<div>html with string</div>'
<%= string.html_safe %> # display as HTML
<%= string %> # display as string
  • To Attempt 3

From the article, escape_javascript used within single or double quotes is safe.

# safe
'<%= j string %>' # or
"<%= j string %>"

# unsafe
<%= j string %>  # or
`<%= j string %>`

So Attempt 3 is XSS safe, also it's the Rails way and is preferred.

And your code could be simplified:

# html() method will replace the original content, so you don't have to remove it first
$('#blog_select_box')
  .html("<%= j options_from_collection_for_select(@blogs, :id, :name) %>");
eux
  • 3,072
  • 5
  • 14