GHSA-9WJQ-CP2P-HRGF: Root-Cause Fix for SVG href Sanitization Bypass in Loofah
Summary
The patch addresses a sanitizer gap in Loofah’s SVG handling by extending local-reference enforcement from only xlink:href to both xlink:href and the SVG 2 plain href attribute. The change updates the safelist model, the scrubber predicate, and regression tests, indicating a direct fix for the underlying attribute-classification error rather than a narrow workaround.
Analysis
Vulnerability
Loofah’s sanitizer enforced SVG local-reference restrictions only for the legacy xlink:href attribute, but not for the SVG 2 plain href attribute. As a result, attacker-controlled SVG content could bypass the intended non-local URL stripping logic by using href instead of xlink:href. The advisory describes this as enabling external resource injection or Cross-Site Scripting through unsanitized SVG references. The root issue is an incomplete model of equivalent SVG link-bearing attributes in the sanitizer, not merely a missing test case. See the official advisory and patch references: GHSA advisory, commit 20867b9.
[VULNERABLE]
attr_name == "xlink:href" &&
[PATCHED]
SafeList::SVG_HREF_ATTRIBUTES.include?(attr_name) &&Patch
The patch introduces a dedicated safelist set for SVG href-like attributes and uses it in the scrubber logic. Specifically, lib/loofah/html5/safelist.rb now defines SVG_HREF_ATTRIBUTES containing both xlink:href and href. In lib/loofah/html5/scrub.rb, the sanitizer no longer hard-codes a check for only xlink:href; instead it applies the local-reference restriction to any attribute in that set. This is a structurally sound change because it centralizes the attribute classification and reduces the chance of future divergence between policy and enforcement. The test suite was also expanded to generate the same allow/deny cases for both attribute names, including newline-prefixed inputs and parser/serializer-specific output behavior. Source: official patch commit.
SVG_HREF_ATTRIBUTES = Set.new([
"xlink:href",
"href",
])The regression tests are especially relevant because they verify both accepted local fragment references such as #foo and rejected non-local URLs such as http://bad.com/foo for both attribute spellings. They also document serializer differences for newline handling in href, which helps prevent false negatives in future test runs.
Review
Pros
- The fix targets the actual trust-boundary mistake: the sanitizer treated only one of two semantically relevant SVG link attributes as security-sensitive.
- Policy is centralized via
SafeList::SVG_HREF_ATTRIBUTES, improving maintainability and making future review of SVG URL-bearing attributes easier. - The scrubber change is minimal and low-risk: it broadens an existing restriction path rather than introducing a new sanitization mechanism.
- Regression coverage was expanded systematically for both
xlink:hrefandhref, including local, non-local, and newline-prefixed cases. - The tests capture parser-specific serialization behavior, which strengthens portability across supported HTML/XML backends.
Cons
- The patch is narrowly scoped to
xlink:hrefandhref; it does not, from the provided diff alone, demonstrate a broader audit of other SVG attributes or elements that may carry navigable or fetch-capable URLs. - The safelist set reduces duplication, but correctness still depends on complete enumeration of all security-relevant SVG URL attributes elsewhere in the sanitizer design.
- The provided patch summary does not show additional negative tests for obfuscated schemes beyond newline-prefixed values, so broader canonicalization coverage cannot be confirmed from the cited sources alone.
Verdict
Root-cause.
This patch appears to remediate the underlying defect by recognizing that SVG 2 plain href must be subject to the same local-reference restriction as xlink:href. The implementation updates both the sanitizer decision point and the attribute taxonomy, and the tests validate the intended behavior for both forms. Based on the supplied sources, this is not a superficial blocklist tweak or a one-off special case; it is a direct correction to the sanitizer’s security model for SVG href attributes. References: patch commit, security advisory, third-party report.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- XSS.rb
Best match for this Loofah/Ruby sanitizer bypass. The advisory describes an SVG href sanitization gap that can lead to Cross-Site Scripting, so a Ruby hands-on XSS lab is the most direct defensive practice target.
- Canine.py
A medium-difficulty XSS lab that helps build defense-in-depth instincts beyond basic escaping. Useful because sanitizer bypasses often require understanding multiple layers of output handling, validation, and safe rendering.
- Self Sabotage.js
Relevant for understanding the client-side impact of sanitizer failures. Since SVG/HTML attribute bypasses can end in browser-side script execution, this medium JavaScript XSS lab complements the server-side Ruby patch context.