65

When I generate a default scaffold, the display tags on show.html.erb have

<%=h @broker.name %>

I know the difference between <% and <%=. What's the "h" do?

Matthias Winkelmann
  • 15,870
  • 7
  • 64
  • 76
neezer
  • 19,720
  • 33
  • 121
  • 220

7 Answers7

98

html escape. It's a method that converts things like < and > into numerical character references so that rendering won't break your html.

JasonTrue
  • 19,244
  • 4
  • 34
  • 61
  • 12
    and in Rails 3 this is done automatically therefore won't be needed. – lulalala Apr 09 '12 at 05:46
  • 1
    @lulalala can you provide a link to backup your claim that this is done automatically in rails 3 (and 4)? – bfcoder Dec 24 '14 at 18:20
  • 1
    @bfcoder, this is in all the current Rails guides and documents. Any string that isn't in a SafeBuffer instance will be html escaped in a view, though you can still call other escaping methods (like json, etc) if you need them. I think this explanation is reasonably complete: http://makandracards.com/makandra/2579-everything-you-know-about-html_safe-is-wrong – JasonTrue Dec 24 '14 at 19:10
  • @JasonTrue Thanks for that article! A most excellent explanation backing up that claim. – bfcoder Dec 24 '14 at 19:58
15

<%=h is actually 2 things happening. You're opening an erb tag (<%=) and calling the Rails method h to escape all symbols.

These two calls are equivalent:

<%=h person.first_name %>
<%= h(person.first_name) %>

The h method is commonly used to escape HTML and Javascript from user-input forms.

David Tuite
  • 22,258
  • 25
  • 106
  • 176
  • I get the <%= part but why exactly is the h() needed in this instance...I know that the h method is used to escape HTML and Javascript from user-input forms but 1) Can't you just say <%= person.first_name %> ? If not why not...i.e., what specific problem is the h() solving? i.e., what would you get if you didn't call the h() method. – user2101068 May 02 '15 at 22:35
15

h is a method alias for html_escape from the ERB::Util class.

Matthias Winkelmann
  • 15,870
  • 7
  • 64
  • 76
Tim Harding
  • 2,875
  • 1
  • 17
  • 10
6

There is also a method in Rack to escape HTML Rack::Utils.escape_html in case you are in Metal and want to escape some HTML.

heycarsten
  • 302
  • 2
  • 5
3

Way late to the party but I'm adding a further explanation to what html_escape is doing to hopefully help other noobs like myself understand what's happening. Rails 3 and later automatically escape all output now and so there are much fewer situations where html_escape aka h() will be needed. The most notable of which is when you intend to use the html_safe method when building links with html in a presenter class etc. For example:

#some_view.html.erb
<span><%= @user.name %></span>  #This is 100% fine and will be automatically escaped by Rails 3+
#Output =>  <span>Brian Kunzig</span>

#Now say we want a link with html that we need preserved!  OMG WHAT ARE DO??
<%=link_to "<span><i class='fa fa-user'></i>#{@user.name}</span>".html_safe  #DANGER!!!

The link above can cause serious problems and open you up to all sorts of xss (cross-site scripting) attacks. The most simple example, if a user saved their name as "<script>alert('omg');</script>" and you used html_safe on it, it will cause any page rendering their supposed name to get an alert saying 'omg'! This is a major problem. To avoid this do:

<%=link_to "<span><i class='fa fa-user'></i>#{h(@user.name)}</span>".html_safe #Winning!

By escaping the potentially tainted data supplied by a user we're homefree!

bkunzi01
  • 4,504
  • 1
  • 18
  • 25
2

h is just alias for html_escape. It is a utility method commonly used to escape html and javascript from user input forms. It converts special charactes into numerical character references so that rendering won't break your html.

For example having

<%= h "<p>Hello World</p>" %>  

will output

<p>Hello World</p>

as text to view, paragraph won't be applied. it wil be encoded as

&lt;p&gt;Hello World&lt;/p&gt;.
Nesha Zoric
  • 6,218
  • 42
  • 34
1

What is h?

h is an alias for html_escape Source code.

What is html_escape?

# a user goes to an online app. 
# writes something on a form. submits the form.
# user writes something malicious on the form:

malicious_string = '<script> steal_everyones_password_hehe </script>'

# the string is saved in the database
# without modification (let's suppose)
# when a html page is retrieved, 
# the string is displayed in a html document
# the browser must display the string. 
# When it does, you don't want
# the malicious javascript to be run.

This would be really bad because the script would run:

<html>
     <script> javascript_runs_and_steals_passwords! </script>
</html>

We need to make that string safe. We do this by ESCAPING from the danger:

html_escape(malicious_string)
# => "&lt;script&gt; if_users_type_in_this_malacious_script &lt;/script&gt;" 

# notice how the < and > disappear? 
# The browswer will not recognise this as a script tag.

html_escape(malicious_string).html_safe?
# => true (now it's safe)
# you can display this string in your webpage without fear

(malicious_string).html_safe?
# => not safe, because we haven't escaped it!

What is the html_safe method?

WARNING: html_safe DOES NOT make something safe, if it is inherently dangerous - you're telling Rails: "no need to escape this string -- I know what i'm doing":

Bad:

html_safe(user_input) # Danger!

Never ever mark any user_input as safe (unless you have a really good reason)!

It will display that code, without escaping it.

Good:

html_safe(i_know_what_im_doing)  # ok, I hope you really do, though!`

# When in doubt, escape from danger:**

h(malicious_string) # => you're safe
html_escape(malicious_string) # => you're safe
BenKoshy
  • 33,477
  • 14
  • 111
  • 80
  • 1
    `h` is an alias for `html_escape` not `html_safe` (as per your link). And `html_escape` *does* make a string safe. Perhaps you meant to say `html_safe`? – Abraham Chan Aug 10 '23 at 21:20
  • @AbrahamChan You are 100% correct. Thank you very much for bringing this to my attention. I have fixed and updated the answer. – BenKoshy Aug 10 '23 at 22:50