Everything you need to know about html_safe
When using embedded erb tags to display content on your rails website, there will be occasions where you’ll want to wrap instance variables in html code. Rails uses the SafeBuffer object to help deal with this code and some of the potential pitfalls. Let’s walk through how SafeBuffer and #html_safe work.
By default, all strings embedded into erb tags will be “escaped” — in other words, the html tags in the string will be replaced with harmless characters. For example:
<%= '<br />' %>
Would appear as follows in the resulting html document:
<br />
You can modify this behavior by calling the #html_safe method on the string. In essence, #html_safe tells the browser that you’ve vetted the string and approve of its contents.
<%= 'br />'.html_safe %>
Results in the following html:
<br />
Let’s see how this actually plays out in real life. A common area where we want to use an erb tag to display html is through a view helper method. In our view, we have the following line of code:
<%= greet_user(@user.username) %>
Which calls the following method:
def greet_user(username) "Greetings, <strong>#{username}</strong>!" end
Unfortunately, this code will not do what the code’s author likely expects. As explained above, all strings embedded in ERB tags are escaped in entirety by default. The resulting HTML would look like this:
Greetings, <strong>SweetBaby123</strong>!
Oops! That’s certainly not what we want. What if we modified our view helper method as follows:
def greet_user(username) "Greetings, <strong>#{username}</strong>!".html_safe end
if the username was SweetBaby123, the resulting HTML code would look like this:
Greetings, <strong>SweetBaby123</strong>!
That looks much better! BUT WAIT. Before you bust out the champaign on a job well done, you should be aware that the above view helper method has a major security pitfall!
If the user was malicious, he could potentially change his username to something dangerous — like an evil JS script! Because #html_safe was called in whole on the string, the malicious script would make it into a user’s browser with no push back from rails:
Greetings, <strong><script>EVIL_JAVA_SCRIPT</script></strong>!
This is not good!
So how do we solve the issue? When defining your view helpers, selectively use html_safe on the areas you KNOW are safe. Allow Ruby to automatically escape unverified content. See below for the right way to handle it:
def greet_user(username) html = "Greetings, <strong>".html_safe html << username html << "</strong>!".html_safe html end
With the above example, even if someone inserts a malicious script as their username, the code will be escaped and it will have no effect:
Greetings, <strong><script>EVIL_JAVA_SCRIPT</script></strong>!
I hope this helps! Stay Safe!











