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!
















