Skip to content

🚨 [security] [ruby] Update loofah 2.25.1 → 2.25.2 (patch)#5941

Open
depfu[bot] wants to merge 1 commit into
developfrom
depfu/update/loofah-2.25.2
Open

🚨 [security] [ruby] Update loofah 2.25.1 → 2.25.2 (patch)#5941
depfu[bot] wants to merge 1 commit into
developfrom
depfu/update/loofah-2.25.2

Conversation

@depfu

@depfu depfu Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🚨 Your current dependencies have known security vulnerabilities 🚨

This dependency update fixes known security vulnerabilities. Please see the details below and assess their impact carefully. We recommend to merge and deploy this as soon as possible!


Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request.

What changed?

↗️ loofah (indirect, 2.25.1 → 2.25.2) · Repo · Changelog

Security Advisories 🚨

🚨 Loofah `allowed_uri?` does not detect `javascript:` URIs split by named whitespace character references

Summary

Loofah::HTML5::Scrub.allowed_uri? does not correctly reject javascript: URIs when the scheme is split or prefixed by the HTML5 named character references 	 (tab) or 
 (line feed).

This is a bypass of the fix for GHSA-46fp-8f5p-pf2m, which handled the equivalent numeric character references (	, 
, 
) but did not cover the named forms.

Details

allowed_uri? decodes HTML entities with CGI.unescapeHTML, which handles numeric character references but not HTML5 named character references. Payloads like java	script:alert(1) are therefore left intact, so the method does not recognize the javascript: scheme and returns true. A browser, however, decodes 	 and 
 to tab and line feed and strips them from the URL during parsing, producing javascript:alert(1).

	 and 
 are the only relevant named character references: across the HTML5 named-character table, they are the only two that decode to characters the WHATWG URL parser strips from a URL (U+0009 and U+000A; there is no named reference for U+000D).   /   decode to U+00A0, which browsers do not strip, so they aren't usable for this bypass.

Note that Loofah's default sanitize() path is not affected, because Nokogiri decodes or entity-escapes HTML entities during parsing before Loofah evaluates the URI protocol. This issue only affects callers of the public allowed_uri? string-level helper that pass it HTML-encoded strings.

Impact

Callers that validate a user-controlled URL with Loofah::HTML5::Scrub.allowed_uri? and then render the approved value into an href or other browser-interpreted URI attribute may be vulnerable to cross-site scripting (XSS). This includes applications that call allowed_uri? directly, as well as higher-level features built on top of it, such as Action Text 8.2's markdown link validation.

Mitigation

Upgrade to Loofah >= 2.25.2.

Credit

Responsibly reported by GitHub user @connorshea.

🚨 Loofah: SVG `href` attribute bypasses local-reference restriction

Summary

Loofah's HTML5 sanitizer restricted only the xlink:href attribute on certain SVG elements to local, same-document references. Browsers also accept a plain href attribute as an alternative to the deprecated xlink:href per the SVG 2 spec, but Loofah did not apply the same restriction to it, allowing those elements to reference arbitrary external documents.

Impact

SVG <use> can load and render external SVG content by reference. If the referenced external SVG is same-origin and contains scripts or other dangerous content, it could execute in the context of the sanitized document. <feImage> can load external images, which can be used for tracking. Modern browsers restrict cross-origin <use> fetches, which limits but does not eliminate the risk.

Applications that sanitize user-supplied SVG (directly, or as part of HTML) with Loofah's default allowlist are affected.

Mitigation

Upgrade to Loofah >= 2.25.2.

Credit

Found by the maintainer, Mike Dalessio, during a security audit.

🚨 Loofah `allowed_uri?` does not detect `javascript:` URIs split by numeric character references without semicolons

Summary

Loofah::HTML5::Scrub.allowed_uri? does not correctly reject javascript: or vbscript: URIs when the scheme is split by a numeric character reference that has no trailing semicolon. A browser decodes such references and resolves the URL to an executable javascript: scheme, while allowed_uri? reports it safe.

This is a bypass of the fix for GHSA-46fp-8f5p-pf2m, which handled numeric character references with a trailing ; (&#9;, &#10;, &#13;) but did not cover the forms without semicolons.

Details

allowed_uri? decodes HTML entities with CGI.unescapeHTML, which decodes numeric character references only when they carry a trailing ;. A reference without a semicolon such as &#58 (colon) or &#9 (tab) is left literal, so the scheme-detection check finds no scheme, and the method falls through to its scheme-less path and returns true.

A browser, however, decodes numeric character references even without a trailing semicolon. An encoded colon such as &#58 becomes the : scheme separator, so javascript&#58alert(1) resolves to javascript:alert(1). Encoded whitespace such as &#9 (tab) is decoded and then stripped from the URL, rejoining the surrounding text, so java&#9script:alert(1) also resolves to javascript:alert(1). In both cases the URL executes while allowed_uri? approved it as safe.

Note that Loofah's default sanitize() path is not affected, because Nokogiri decodes or entity-escapes HTML entities during parsing before Loofah evaluates the URI protocol. This issue only affects callers of the public allowed_uri? string-level helper that pass it HTML-encoded strings.

Impact

Callers that validate a user-controlled URL with Loofah::HTML5::Scrub.allowed_uri? and then render the approved value into an href or other browser-interpreted URI attribute may be vulnerable to cross-site scripting (XSS). This includes applications that call allowed_uri? directly, as well as higher-level features built on top of it, such as Action Text 8.2's markdown link validation.

Mitigation

Upgrade to Loofah >= 2.25.2.

Credit

Responsibly reported by GitHub user @MoonFuji.

Release Notes

2.25.2

2.25.2 / 2026-07-15

Security

  • Ensure Loofah::HTML5::Scrub.allowed_uri? recognizes numeric character references without semicolons (e.g. javascript&#58alert(1)), which browsers decode and execute, and rejects schemes split by them. See GHSA-5qhf-9phg-95m2. @flavorjones
  • Ensure Loofah::HTML5::Scrub.allowed_uri? recognizes the named character references &Tab; and &NewLine;, which CGI.unescapeHTML does not decode and browsers strip from URIs, and rejects schemes split by them (e.g. java&Tab;script:alert(1)). See GHSA-8whx-365g-h9vv. @flavorjones
  • Ensure that both href and xlink:href attributes on SVG elements like use are restricted to local (same-document) references. Previously only xlink:href was restricted, allowing the SVG 2 href attribute to reference external documents. See GHSA-9wjq-cp2p-hrgf. @flavorjones

Improved

  • Harden data: URI mediatype parsing in Loofah::HTML5::Scrub.allowed_uri?. The mediatype is now parsed following the WHATWG data: URL spec and RFC 2397 instead of simply being split on a colon. A data: URI with an omitted or malformed mediatype is now treated as text/plain and allowed, and one without the required comma is now rejected. #305 @flavorjones
  • Remove feed from the default set of allowed protocols. The feed URI scheme was never accepted as a standard protocol, and no major browser supports it. Removing it reduces the attack surface particularly for non-browser contexts. #304 @flavorjones
  • Remove a vestigial &#x70 alternative from Loofah::HTML5::SafeList::PROTOCOL_SEPARATOR. This appears to be an ancient typo dating back to pre-extraction Rails circa 2007. #305 @flavorjones

Does any of this look wrong? Please let us know.

Commits

See the full diff on Github. The new version differs by 14 commits:


Depfu Status

Depfu will automatically keep this PR conflict-free, as long as you don't add any commits to this branch yourself. You can also trigger a rebase manually by commenting with @depfu rebase.

All Depfu comment commands
@​depfu rebase
Rebases against your default branch and redoes this update
@​depfu recreate
Recreates this PR, overwriting any edits that you've made to it
@​depfu merge
Merges this PR once your tests are passing and conflicts are resolved
@​depfu cancel merge
Cancels automatic merging of this PR
@​depfu close
Closes this PR and deletes the branch
@​depfu reopen
Restores the branch and reopens this PR (if it's closed)
@​depfu pause
Ignores all future updates for this dependency and closes this PR
@​depfu pause [minor|major]
Ignores all future minor/major updates for this dependency and closes this PR
@​depfu resume
Future versions of this dependency will create PRs again (leaves this PR as is)

@depfu depfu Bot added dependencies Pull requests that update a dependency file Security Update A label to identify dependency updates containing security fixes labels Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.83%. Comparing base (25cb3b6) to head (d0fd25c).

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #5941      +/-   ##
===========================================
- Coverage    84.86%   84.83%   -0.03%     
===========================================
  Files         1494     1494              
  Lines        33957    33957              
  Branches      3618     3618              
===========================================
- Hits         28816    28806      -10     
- Misses        4295     4301       +6     
- Partials       846      850       +4     
Flag Coverage Δ
javascript 76.31% <ø> (ø)
ruby 84.71% <ø> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file Security Update A label to identify dependency updates containing security fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants