Rails - protection against code injection and XSS

Rails 3 has some pretty good protections switched on by default which will catch a lot of common security issues.

Specifically output encoding will help mitigate XSS attacks, the CSRF tokens are enabled by default on all forms which should help here, and as long as you use it correctly ActiveRecord or other ORMs can help with mitigating SQL injection.

On the input validation front there are obviously some things to watch for. Rails won't do input validation for you by default, so if data entered into your app is transferred to other web applications, there's still the risk of XSS attacks occurring.

That said, Rails does support validations in the model, and I'd recommend doing white-list validation of input there, if possible.

On the SQL injection front, it's still possible to use raw SQL with ActiveRecord, and if you do that, then the usual problems with SQL injection can occur, so again white-list validation of all input is useful.

Beyond that there's several things still to watch for. the base Rails installation doesn't provide authorisation/authentication, so that either has to come from a plugin or be written by the developer.

One downside to the RESTful style URLs that a rails app will typically produce is that it's usually easy for an attacker to try to break authorization by modifying the URL. For example a URL of http://mysite/users/1 which shows the first user, could be easily modified to have a 2 or more. It's not that it's less secure but it makes it easier for attackers to attempt to bypass authorization controls.

There's a couple of good information sources for Rails security that are well worth reading for more information.

The OWASP rails security guide is here and there's also a book Security on Rails from Pragmatic Programmers which although it focuses on Rails 2.3 still has a lot of good information to consider (note that Security on Rails is now out of print).


The OWASP XSS Cheat Sheet is a great resource to understand all the ways XSS can happen:

  • RULE #0 - Never Insert Untrusted Data Except in Allowed Locations
  • RULE #1 - HTML Escape Before Inserting Untrusted Data into HTML Element Content
  • RULE #2 - Attribute Escape Before Inserting Untrusted Data into HTML Common Attributes
  • RULE #3 - JavaScript Escape Before Inserting Untrusted Data into HTML JavaScript Data Values
  • RULE #4 - CSS Escape Before Inserting Untrusted Data into HTML Style Property Values
  • RULE #5 - URL Escape Before Inserting Untrusted Data into HTML URL Parameter Values
  • RULE #6 - Use an HTML Policy engine to validate or clean user-driven HTML in an outbound way
  • RULE #7 - Prevent DOM-based XSS

Not all of the rules above are taken care of by Rails automatically and it depends on the version:

Rails 3.x = "If a plain String is passed into a <%= %>, Rails always escapes it"
Rails 2.x = You need to use h() method (or use something like Cross Site Sniper or Safe Erb)

White listing does rule the day: If you expect a two-letter U.S. postal abbreviation, then use validations to accept only that.

General security guide: http://guides.rubyonrails.org/security.html