Search code examples
ruby-on-railsrubyruby-on-rails-5

Properly Escaping a String inside a View


I've read in multiple places that as of Rails 3 you no longer have to use html_escape "some string" to actually escape a string in a view and that simply writing <%= "some string" %> would escape the string by default. However, I cannot find this information in the docs. I read through the XSS in the Rails guides section that stated this:

https://guides.rubyonrails.org/security.html#cross-site-scripting-xss

As a second step, it is good practice to escape all output of the application, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). Use escapeHTML() (or its alias h()) method to replace the HTML input characters &, ", <, and > by their uninterpreted representations in HTML (&, ", <, and >).

Then I see several blogs that state that it is escaped by default. For example: https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/

https://dzone.com/articles/preventing-cross-site-scripting-vulnerabilities-wh


Solution

  • Found it:

    https://guides.rubyonrails.org/3_0_release_notes.html

    "7.4.3 Other Changes You no longer need to call h(string) to escape HTML output, it is on by default in all view templates. If you want the unescaped string, call raw(string)."


    escapeHTML() (or its alias h()) are from CGI::escapeHTML, which is a Ruby API implementation. If you aren't using Rails you still have a way to escape HTML. Rails may do some automagical handling of HTML in ERB files for display, and that is what you are probably referring to with html_escape "some string" and <%= "some string" %>. I think you are possibly confusing html_escape which you might need when displaying urls and such that are stored in the DB and you want the ERB processor to not mess it up? I know sometimes, particularly in .js.erb files I need to escape some things to get the result I was expecting. This is different than sanitizing. It seems in your example they are referring to something that you might accept and then redisplay, like a search string. If you put <i>hello</i> into a search box you would want to sanitize the input before passing it to the back end, or if you are using some javascript to filter you might want to escape it both for security reasons and to let it re-display correctly in the search box after you've filtered.

    Edit: I was not able to find the answer to your comment in the ri doc either. But I tried:

    <%= "<b>hello</b>" %>
    <%= h("<b>hello</b>") %>
    

    And got the same result in the browser:

    &lt;b&gt;hello&lt;/b&gt;
    &lt;b&gt;hello&lt;/b&gt;
    

    So if you are asking if it is true, then I would say yes.