Loofah
Loofah is a Ruby library for manipulating and transforming HTML and XML documents and fragments, built on top of Nokogiri. It gives you a small, sharp tool, the scrubber, that walks a parsed document node by node and changes it, plus a set of ready-made scrubbers that sanitize untrusted HTML using an allowlist derived from the html5lib project.
Loofah is the sanitization engine underneath rails-html-sanitizer, which means it quietly cleans user-generated HTML in a very large number of Ruby on Rails applications. You can also use it directly in any Ruby program.
The Problem It Solves
Accepting HTML from users (comments, rich-text editors, imported emails, pasted Word documents) is dangerous: a single <script> tag, onerror= attribute, or javascript: link turns stored content into a cross-site scripting (XSS) attack. Regular expressions cannot reliably remove these, because HTML is not a regular language and browsers are extremely forgiving parsers.
Loofah takes the robust approach:
- Parse the input with a real HTML parser (Nokogiri's libxml2-based HTML4 parser, or its Gumbo-based HTML5 parser).
- Walk the resulting tree and apply a scrubber to every node.
- Serialize the cleaned tree back to HTML or plain text.
Because the scrubber sees the same tree a browser would build, tricks that confuse string-based filters (unclosed tags, odd casing, encoded characters) do not get through.
Key Features
- Four sanitizing strategies for unknown or unsafe tags: strip, prune, escape, and whitewash.
- Link and text transformations:
:nofollow,:noopener,:noreferrer,:targetblank,:unprintable, and:double_breakpoint. - Custom scrubbers written as a block or a class, run top-down or bottom-up, with the ability to stop descending into a subtree.
- HTML5, HTML4, and XML support through Loofah's subclasses of Nokogiri's document classes, covered in Documents and Fragments.
- Scrub anything: whole documents, fragments, a single node, or a
NodeSetfrom a CSS or XPath query. - Plain-text output with
textandto_text, which knows to put newlines around block elements and<br>tags. - Attribute, URI, and CSS sanitization with a well-defined safelist and a standalone
allowed_uri?check and CSS scrubber. - Drop-in replacements for the Rails
strip_tags,sanitize, andsanitize_csshelpers inLoofah::Helpers.
A Short Example
require "loofah"
unsafe_html = "ohai! <div>div is safe</div> <script>but script is not</script>"
doc = Loofah.html5_fragment(unsafe_html).scrub!(:prune)
doc.to_s # => "ohai! <div>div is safe</div> "
doc.text # => "ohai! div is safe "
And a custom transformation:
span2div = Loofah::Scrubber.new do |node|
node.name = "div" if node.name == "span"
end
Loofah.html5_fragment("<span>foo</span><p>bar</p>").scrub!(span2div).to_s
# => "<div>foo</div><p>bar</p>"
How It Works
Loofah's document and fragment classes (Loofah::HTML5::Document, Loofah::HTML4::DocumentFragment, Loofah::XML::Document, and so on) are subclasses of the matching Nokogiri classes, so everything you know about Nokogiri (css, xpath, at_css, node manipulation) still works. Loofah adds:
- a
scrub!method on documents, fragments, nodes, and node sets, which resolves a symbol like:pruneto a built-inLoofah::Scrubberand traverses the tree with it; - HTML-aware
to_s,text, andto_textmethods for HTML documents and fragments; - removal of comments that sit outside the
<html>element when an HTML document is parsed.
The built-in sanitizers check each element name against Loofah::HTML5::SafeList, clean the attributes of allowed elements (removing unknown attributes, unsafe URIs, and unsafe CSS), and then strip, prune, escape, or whitewash everything else. The Internals page walks through this step by step.
When to Use Loofah
Use Loofah when you need to:
- sanitize untrusted HTML with sensible defaults and little configuration;
- write your own document transformations (rename tags, rewrite links, remove nodes) with a simple visitor API on top of Nokogiri;
- turn HTML into readable plain text.
Consider alternatives when:
- you need fine-grained, declarative control over exactly which tags and attributes are allowed per element. The README points to
rgrove/sanitize, another Nokogiri-based library with more configuration options, and torails/rails-html-sanitizer, which builds on Loofah and adds configurable allowed tags and attributes; - you only need to parse or query HTML, in which case plain Nokogiri is enough.
For Active Record integration, the README mentions the separate loofah-activerecord gem.
Project Status
Loofah is actively maintained by Mike Dalessio (the Nokogiri maintainer) and Bryan Helmkamp. The current version in the repository is 2.25.2. It is released under the MIT License. Security issues are handled through GitHub security advisories; recent releases have tightened URI checking against encoded javascript: schemes.
Release notes are in the CHANGELOG. The library was originally called "Dryopteris".
Where to Go Next
- Installation: requirements and how to check that HTML5 support is available.
- Quick Start: sanitize your first piece of HTML in a few minutes.
- Documents and Fragments: choosing the right parser and entry point.
- Sanitizing Scrubbers:
:strip,:prune,:escape,:whitewashcompared. - Custom Scrubbers: write your own transformations.
- API Reference: every public method and constant.
- Troubleshooting: surprising behaviors and how to handle them.