Escaping HTML in Rails

Readonly picture Readonly · Mar 30, 2009 · Viewed 22.6k times · Source

What is the recommended way to escape HTML to prevent XSS vulnerabilities in Rails apps?

Should you allow the user to put any text into the database but escape it when displaying it? Should you add before_save filters to escape the input?

Answer

Luke Francl picture Luke Francl · Mar 31, 2009

There are three basic approaches to this problem.

  1. use h() in your views. The downside here is that if you forget, you get pwnd.
  2. Use a plugin that escapes content when it is saved. My plugin xss_terminate does this. Then you don't have to use h() in your views (mostly). There are others that work on the controller level. The downsides here are (a) if there's a bug in the escaping code, you could get XSS in your database; and (b) There are corner cases where you'll still want to use h().
  3. Use a plugin that escapes content when it is displayed. CrossSiteSniper is probably the best known of these. This aliases your attributes so that when you call foo.name it escapes the content. There's a way around it if you need the content unescaped. I like this plugin but I'm not wild about letting XSS into my database in the first place...

Then there are some hybrid approaches.

There's no reason why you can't use xss_terminate and CrossSiteSniper at the same time.

There's also a ERb implementation called Erubis that can be configured so that any call like <%= foo.name %> is escaped -- the equivalent of <%= h(foo.name) %>. Unfortunately, Erubis always seems to lag behind Rails and so using it can slow you down.

If you want to read more, I wrote a blog post (which Xavor kindly linked to) about using xss_terminate.