Hanami makes available a set of escape helpers, to increase the security of our web applications. They are public methods that are available both in views and templates.

It’s a method called (aliased as #h), that escapes the input.

Returns

  1. <p>&lt;script&gt;alert(&apos;xss&apos;)&lt;&#x2F;script&gt;</p>

HTML attributes are more complex to escape, because they involve attribute delimitation chars (eg. single or double quotes).

We have an extra helper for this specific task: #escape_html_attribute (aliased as #ha) This should be used only when the value of an attribute comes from a user input.

  1. <img src="/path/to/avatar.png" title="<%= ha(user.name) %>'s Avatar">

In the profile page we have a link like this:

A malicious user can edit their profile, by entering javascript code as the website URL. When somebody else clicks on that link, they can receive an XSS attack.

Example:

  1. <a href="javascript:alert('hack!');">Website</a>

The solution to this problem is to wrap the output with the #escape_url (aliased as #hu) helper.

It whitelists URLs that use http, https, and mailto schemes, everything else is scraped.

  1. <%= link_to "Website", hu(user.website_url) %>

In the code above, we’re restricting to URLs that only use HTTPS.

There are cases when we want to print the raw contents. Please be careful with this, because unescaped contents can open a breach for XSS attacks.

The helper is called #raw.

If we want to escape a specific local:

  1. # apps/web/controllers/snippets/show.rb
  2. module Web
  3. module Controllers
  4. module Snippets
  5. class Show
  6. expose :snippet
  7. def call(params)
  8. @snippet = "<h1>Hello World</h1>"
  9. end
  10. end
  11. end
  12. end
  13. end
  1. # apps/web/views/snippets/show.rb
  2. module Web
  3. module Views
  4. module Snippets
  5. class Show
  6. include Web::View
  7. def snippet
  8. end
  9. end
  10. end
  11. end

Entire Output

We can also return unescaped output for the entire view:

  1. # apps/web/views/books/json_show.rb
  2. require 'json'
  3. module Web
  4. module Views
  5. module Books
  6. class JsonShow < Show
  7. format :json
  8. def render
  9. raw JSON.generate(book.to_h)
  10. end
  11. end
  12. end