I'm working on a Rails app, and I have some text that is almost html_safe. Specifically, I need to allow the tags mentioned in this post, and escape all others.

Rails will either escape all the tags, without a whitelist, or remove the tags, with a whitelist. I want to escape the tags, with a whitelist.

For example, with a whitelist of ['foo', 'bar'], I would expect something like:

> fancy_escape("<foo>yay</foo> <bad>nasty</bad>")
=> "<foo>yay</foo> &lt;bad&gt;nasty&lt;/bad&gt"


  • Must work with Ruby 2.2.2 and Rails 4.2.3
  • Must take in a string and output a string-like thing
  • Must escape, not strip, HTML tags that aren't in a whitelist
  • Whitelist must be easily definable, ideally globally

What can do this?

  • Do some of the whitelisted tags have attributes? – Nicolas Raoul May 18 '16 at 4:03
  • @NicolasRaoul I don't think they did, but I'm honestly not sure what I needed this for anymore. – Undo May 18 '16 at 13:48

I have used something like this:

text = CGI.escapeHTML(text)
text = CGI.unescapeElement(text, %w[foo bar])

Unfortunately, the problem I'm having now is that this doesn't account for invalid tag attributes, so I'm currently trying to figure out a clever way to escape elements that have valid HTML tag types, but invalid attributes. Like if <b>bold</b> is valid (and will show bold with html_safe), and <b attr="value">bold</b> is valid (and will show bold with html_safe), but <b other-attr="value">bold</b> is invalid (and will escape, so that it renders as seen in this post with html_safe).


Why not simply use a regex? Something along the lines of a regex to match all tags, a white list of tags not to escape and for any tags not in the white list substitute the escaped version, it might be quicker to use a regex to replace all of the tags with escaped tags and then another to put back the ones on the white list but that depends on the length of the white list and whether your content is likely to have already escaped, white listed, items that you don't wish to un-escape.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.