Stay safe while using html_safe in Rails
Whether you’re a junior dev, product designer or senior level software engineer, it’s easy to fall on your face when using `html_safe` in Rails.
The thing about this method is: it’s terribly named. I mean really, it’s a horrible name. When you call a method on an object which transforms the original object, the method name should describe the transformation which is about to happen.
The html_safe method makes you think that the transformation you’re doing to the string is actually going to be safe. It can be safe. It can be very unsafe, too.
I’m going to go on record stating that we should call this method something more sane, like: html_beware. Why beware? Because as a code committer, you should be very aware of the string that you’re calling this method on. If the string has input that is user controlled of any kind, you should certainly not call “html_safe” on it. This method should make you think twice about what you’re doing, and by calling it safe, it certainly doesn’t make you think at all.
Let’s go over some code examples and explain exactly how html_safe works, and why it’s unsafe in certain contexts.
Now that we’ve looked at how to use html_safe properly, let’s look an example of how we at Reverb fell on our face. Not too long ago we shipped some code which allowed user-controlled input to be inserted into the DOM. This resulted in a stored XSS attack, which you can see here:
Here’s the bad code:
And here’s how we fixed it:
While there’s nothing inherently harmful about a javascript alert besides a minor annoyance, this attack vector illustrates that a user can inject any type of html tags into the DOM, including script tags. This could be especially disastrous if this vector was used to steal session cookies or login information. Thankfully we caught this error ourselves and it was not exploited.
Keep this in mind while you’re building your next awesome project and know exactly where the string comes from that you’re adding html_safe to. And even if you’re not building something new and have inherited an older codebase, consider grep’ing your codebase looking for string interpolations combined with html_safe:
.*(\+|\}).*html_safe
So while nothing is perfect, including this method name, in conclusion we have learned that it pays to be careful about what type of user data you’re working with. Here at Reverb, we believe in owning mistakes and fully understanding why they happened.
That being said, we also believe that nothing is perfect and mistakes will happen. If you believe you’ve found a bug on our platform, please securely and responsibly disclose it to us at security@reverb.com. We will work with you to confirm, close and patch the hole. We do offer bounty for critical bugs and swag for bugs with a lower risk profile.
Until next time, stay html_safe!