2.25.3 / 2026-11-01
Security
- Ensure
Loofah::HTML5::Scrub.allowed_uri?rejects schemes split by a numeric character reference without a semicolon that ends at a characterallowed_uri?strips (e.g.javascript: alert(1)) or at another character reference (e.g.javascript:alert(1)). Character references are now decoded before anything is stripped, as browsers do. See GHSA-p9wj-w8xq-vjx6. @flavorjones - Ensure
Loofah::HTML5::Scrub.allowed_uri?recognizes the named character reference/, whichCGI.unescapeHTMLdoes not decode and browsers read as/, and rejectsdata:URIs that disguise a disallowed mediatype with it (e.g.data:text/html,<script>alert(1)</script>). Previously that mediatype was treated as malformed and fell back to the allowedtext/plain. Only v2.25.2 is affected. See GHSA-jcff-cj73-4w4f. @flavorjones - Ensure
Loofah::HTML5::Scrub.scrub_cssdoes not decode CSS escapes in identifiers. Previously, escaped parentheses (e.g.url\28 http://example.com/\29) came out as a liveurl(), which could make the viewer's browser fetch an attacker-chosen URL. See GHSA-m3x9-938q-5767. @flavorjones - Ensure that
hrefandxlink:hrefon SVGtextPathandmpathelements are restricted to local (same-document) references. PreviouslySVG_ALLOW_LOCAL_HREFspelledtextPathin lowercase, which never matched the name the HTML5 parser assigns inside<svg>, and omittedmpathentirely. See GHSA-345x-3rq2-jfrm. @flavorjones - Fix quadratic-time scrubbing of the
hrefandxlink:hrefattributes of SVG elements. Only Ruby 3.1 and earlier are affected, because Ruby 3.2 introduced linear-time regexp matching. See GHSA-mf2j-8f84-cc9q. @flavorjones - Ensure HTML5 scrubber output does not turn into new markup when a browser parses it again. The fix is in Nokogiri v1.19.5, which escapes
<and>in attribute values as the HTML standard requires, so Loofah now requires Nokogiri >= 1.19.5. See GHSA-h6v6-rg66-fqj4. @flavorjones @hackvertor
Dependencies
- Loofah now requires Ruby >= 3.2, the minimum that Nokogiri v1.19.x supports. We don't like dropping Ruby versions in a patch release, and we're sorry for the inconvenience, but it's the only way to make sure everyone gets the security fix in GHSA-h6v6-rg66-fqj4.
Added
Loofah::HTML5::Scrub.prefixed_attribute_nameandLoofah::HTML5::Scrub.scrub_attribute_valueexpose the html5lib attribute name and value rules, so downstream consumers can apply them instead of carrying their own copy. @flavorjones
Fixed
- Fix
:double_breakpoint, which left document fragments unchanged despite its documented example. The scrubber now changes only paragraphs inside the scrubbed node, and its run time on a document grows linearly, not quadratically, with the paragraph count. #309 @OskarEichler - Fix
:whitewash, which passed CDATA sections through unchanged. Markup inside a CDATA section inLoofah.xml_fragmentorLoofah.xml_documentsurvived scrubbing and became live elements if the output was later parsed as HTML. The scrubber now escapes CDATA content, as:strip,:pruneand:escapealready do. On JRuby, every sanitizer now emits escaped CDATA content as a CDATA section, as on CRuby, instead of a text node that double-escaped it. #313 @flavorjones (reported by @MegaManSec) - Fix
:double_breakpoint, which raisedNoMethodErroron a paragraph that ends with a<br>after a double break. #314 @flavorjones (reported by @MegaManSec) - Fix
Loofah::HTML5::Scrub.allowed_uri?, which raisedEncoding::CompatibilityErroron a string in an encoding other than UTF-8 andArgumentErroron invalid UTF-8. It now transcodes the input to UTF-8 and returnsfalsewhen the input has an invalid byte sequence or no UTF-8 representation. #315 @flavorjones
New Contributors
- @OskarEichler made their first contribution in #309
Full Changelog: v2.25.2...v2.25.3