Prevent Cross-site Scripting Attacks with Rails 2.3.5 and rails_xss

Earlier this week, the Rails core team released Rails 2.3.5 which introduces a major new feature: support for automatic cross-site scripting protection via the rails_xss plugin. rails_xss switches the default behavior of Rails to automatically escape all unsafe strings emitted into the view.

Why does this matter? Well, in order to prevent cross-site scripting attacks, user-entered data displayed by an application must be filtered to escape HTML tag characters so that they are displayed rather than used as mark-up. In previous versions of Rails the h helper method must be explicitly called to escape a string. This means that if you miss even one string in your application you’ve left a potentially dangerous security hole.

rails_xss enhances the String class with the concept of HTML safety. By default a string is assumed not to be HTML safe. Each time a string is copied into the view, it is evaluated for safeness and escaped if not safe. Strings can be explicitly set safe by calling the html_safe! method.

Adding this plugin to an existing application should be pretty painless as h will still return escaped strings. The plugin also provides the view helper method raw which acts as the opposite of h: strings passed through raw will be copied into the response body without any escaping.

Helper methods which emit HTML may need to have html_safe! called on the resulting string or use the raw helper method. Another possible gotcha is that in testing I noticed some small kinks. The largest being that button_to‘s output isn’t set to HTML safe so it will dump a bunch of HTML on the page rather than the button. This can be worked around by using the raw helper along with button_to, and I assume it’ll be fixed shortly.

rails_xss also changes the default template handler from ERB to Erubis so you may see some performance improvement in your views as Erubis is said to be three times faster than ERB. The escaping behavior and Erubis will both be default in Rails 3.0.

To get started:

Upgrade to Rails 2.3.5

gem install erubis

script/plugin install git://github.com/NZKoz/rails_xss.git

After installation your application will output strings with escaping by default:

5 Comments

William Pietri says:

Wow, that’s great to hear. It always blew my mind that Rails didn’t work this way from the start. In other languages I’ve often ended up with something like an HtmlString class to signal the (few) strings that are actually raw HTML, rather than honest strings; sounds like this is reasonably close. Thanks for posting this.

December 2, 2009 at 6:18 am

Yarrow says:

Is the third line accurate? From the article and the rails_xss README I’d have expected the .html_safe! version to be “Not escaped”.

December 2, 2009 at 10:18 am

John Pignata says:

Yarrow – No, that is totally a typo. Thanks for the catch! I’ve updated it in the post.

December 2, 2009 at 10:41 am

John Pignata says:

There’s an interesting thread on the rails-core list about rails_xss and what it means for plugin/gem authors who want to support it. Users have reported problems with will_paginate and rails_xss cooperating.

Are you running it on this site? Because if you are, it is rather broken. https://pivotallabs.com/login has a potential XSS on it since you do allow user-entered invalid Unicode characters to be output unfiltered. This can trip up IE’s UTF-8 parser which can lead to script injection.