CVE-2026-126206: CVE-2026-126206: Cross-Site Scripting via HTML5 Named Solidus Entity in Loofah URI Validator
CVE-2026-126206: Cross-Site Scripting via HTML5 Named Solidus Entity in Loofah URI Validator Vulnerability ID: CVE-2026-126206 CVSS Score: 5.3 Published: 2026-11-12 CVE-2026-126206 (GHSA-jcff-cj73-4w4f) is a Cross-S
CVE-2026-126206: Cross-Site Scripting via HTML5 Named Solidus Entity in Loofah URI Validator
Vulnerability ID: CVE-2026-126206
CVSS Score: 5.3
Published: 2026-11-12
CVE-2026-126206 (GHSA-jcff-cj73-4w4f) is a Cross-Site Scripting (XSS) vulnerability in version 2.25.2 of the Loofah Ruby gem. The vulnerability stems from an incomplete character reference normalization routine in the Loofah::HTML5::Scrub.allowed_uri? method, which fails to decode the HTML5 named character reference / (representing the solidus character /). Consequently, a crafted data: URI such as data:text/html,<script>alert(1)</script> bypasses mediatype validation by triggering the WHATWG MIME parser fallback to text/plain, while web browsers later resolve / to / and execute the payload as text/html.
TL;DR
Loofah 2.25.2 fails to decode the HTML5 named character reference / (/) inside Loofah::HTML5::Scrub.allowed_uri? (also exposed via Rails::HTML::Sanitizer.allowed_uri?). Attackers can supply data:text/html,<script>... to bypass URI validation as text/plain and achieve Cross-Site Scripting (XSS) when the URI is rendered into an HTML attribute.
β οΈ Exploit Status: POC
Technical Details
- CVE / Advisory ID: CVE-2026-126206 / GHSA-jcff-cj73-4w4f
- Vulnerability Class: CWE-79 (Cross-Site Scripting) / CWE-184 (Incomplete List of Disallowed Inputs)
- CVSS v4.0 Score: 5.3 Medium (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N)
- Affected Component: Loofah::HTML5::Scrub.allowed_uri? (loofah gem = 2.25.2)
- Patched Version: loofah >= 2.25.3
- Attack Vector: Network (Crafted data: URI using / HTML5 entity)
- Exploit Status: Proof-of-Concept (PoC) Publicly Available
- CISA KEV Status: Not Listed
Affected Systems
- loofah Ruby gem (version 2.25.2)
- rails-html-sanitizer (when invoking Rails::HTML::Sanitizer.allowed_uri? with loofah 2.25.2)
-
loofah: = 2.25.2 (Fixed in:
2.25.3)
Code Analysis
Commit: ad92002
Ensure Loofah::HTML5::Scrub.allowed_uri? recognizes the named character reference / and rejects data: URIs that disguise a disallowed mediatype with it.
diff --git a/lib/loofah/html5/scrub.rb b/lib/loofah/html5/scrub.rb
index 2a35090..e8b524a 100644
--- a/lib/loofah/html5/scrub.rb
+++ b/lib/loofah/html5/scrub.rb
@@ -53,6 +53,15 @@ module Scrub
# URIs. CGI.unescapeHTML does not decode these, so they are handled explicitly.
WHITESPACE_CHARACTER_REFERENCES = /&(Tab|NewLine);/
+ # HTML5 named character references for the delimiters that decide how a URI parses:
+ # ":" ends the scheme, and "/" separates the type and subtype of a data: mediatype.
+ # CGI.unescapeHTML does not decode these either. Together with
+ # WHITESPACE_CHARACTER_REFERENCES these are every named character reference that
+ # decodes to U+0009, U+000A, U+002F, or U+003A, so no other named reference can
+ # change how a URI parses.
+ DELIMITER_CHARACTER_REFERENCES = { ":" => ":", "/" => "/" }.freeze
+ DELIMITER_CHARACTER_REFERENCE = Regexp.union(DELIMITER_CHARACTER_REFERENCES.keys)
+
class << self
def allowed_element?(element_name)
::Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2.include?(element_name)
@@ -234,12 +243,12 @@ def allowed_uri?(uri_string)
# also decode the semicolon-less ones, which browsers still decode and execute. Normalizing
# more aggressively than a browser only rejects more, which is safe. Control characters are
# stripped both before and after decoding, since decoding can produce them. That strip must
- # precede WHITESPACE_CHARACTER_REFERENCES: removing a control character can reveal a named
- # whitespace reference.
+ # precede the named reference substitutions: removing a control character can reveal a
+ # named reference.
uri_string = decode_numeric_character_references(CGI.unescapeHTML(uri_string.gsub(CONTROL_CHARACTERS, "")))
uri_string.gsub!(CONTROL_CHARACTERS, "")
uri_string.gsub!(WHITESPACE_CHARACTER_REFERENCES, "")
- uri_string.gsub!(":", ":")
+ uri_string.gsub!(DELIMITER_CHARACTER_REFERENCE, DELIMITER_CHARACTER_REFERENCES)
uri_string.downcase!
if URI_PROTOCOL_REGEX.match?(uri_string)
protocol = uri_string.split(SafeList::PROTOCOL_SEPARATOR)[0]
Exploit Details
-
GitHub Security Advisory: Official advisory containing functional proof-of-concept
data:text/htmlpayloads. -
GitHub Fix Commit & Unit Tests: Upstream unit tests demonstrating plaintext, base64, double-encoded, and control-character-injected
/bypass vectors.
Mitigation Strategies
- Upgrade the
loofahRuby gem to version 2.25.3 or newer across all environments. - Prefer full DOM fragment sanitization (
Loofah.scrub_fragmentor Railssanitizehelper) over standalone string validation viaallowed_uri?. - Ensure all user-supplied URI strings rendered into HTML attributes pass through standard attribute escaping helpers (such as Rails
link_toortag.a) rather than raw.html_safestring interpolation.
Remediation Steps:
- Audit project
Gemfile.lockfiles usingbundle list | grep loofahorbundle exec bundler-audit check --updateto identify instances ofloofahversion2.25.2. - Search application source code (
app/,lib/,config/) for direct invocations ofLoofah::HTML5::Scrub.allowed_uri?orRails::HTML::Sanitizer.allowed_uri?. - Update
Gemfileto requiregem "loofah", ">= 2.25.3"and executebundle update loofah. - Run the application test suite and redeploy affected services.
References
- CVE-2026-126206 Official CVE Record
- GitHub Security Advisory GHSA-jcff-cj73-4w4f
- Loofah Fix Commit ad92002966053309f83b550861e2ef04bc714744
- Loofah Pull Request #324
- Loofah v2.25.3 Release Notes
- RubySec Advisory Database Entry for GHSA-jcff-cj73-4w4f
- Loofah GitHub Repository
Read the full report for CVE-2026-126206 on our website for more details including interactive diagrams and full exploit analysis.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.