{"id":"CVE-2026-126203","kind":"vulnerability","aliases":["CVE-2026-126203","GHSA-h6v6-rg66-fqj4"],"related":[],"title":"Loofah: Mutation XSS in the HTML5 scrubbers through unescaped attribute values","description":"## Summary\n\nLoofah's HTML5 scrubbers could emit output that a browser parses into different markup, allowing mutation XSS. Nokogiri < 1.19.5 did not escape `<` and `>` in attribute values. When the output contained certain MathML, a browser treated markup inside an allowed attribute as live HTML. The `:strip` scrubber is affected in every browser. The `:prune` and `:escape` scrubbers are affected in WebKit browsers such as Safari.\n\nNokogiri 1.19.5 escapes `<` and `>` in attribute values, as the HTML standard requires. Loofah 2.25.3 requires Nokogiri >= 1.19.5.\n\n## Impact\n\nApplications that sanitize untrusted HTML with Loofah's HTML5 API (`Loofah.html5_fragment`, `Loofah.html5_document` and the `scrub_html5_*` methods) and display the result to other people are affected, including with the default allowlist.\n\nNot affected: Loofah's HTML4 API (including `Loofah::Helpers.sanitize`), the `:whitewash` scrubber, rails-html-sanitizer's default configuration, and JRuby.\n\n## Mitigation\n\nUpgrade to Loofah >= 2.25.3, or upgrade Nokogiri to >= 1.19.5.","summary":"Loofah's HTML5 scrubbers can emit markup that a browser parses differently, so attribute content inside allowed MathML becomes live HTML. An attacker who supplies sanitized input that other users view can run script in their browser.","severity":"medium","cvss":6.1,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"loofah","fixed":["2.25.3"],"affected":">= 2.21.0, < 2.25.3","ecosystem":"rubygems"}],"ecosystems":["rubygems"],"tags":["cwe-116","cwe-79","loofah","nokogiri","package","rails","rails-html-sanitizer","ruby"],"not_affected_if":["html4-api-only","jruby","rails-html-sanitizer-default-config","whitewash-scrubber"],"how_to_check":"- Check the Loofah version in `Gemfile.lock` for `loofah` below `2.25.3`\n- Check the Nokogiri version in `Gemfile.lock` for `nokogiri` below `1.19.5`\n- Search the code for `Loofah.html5_fragment`, `Loofah.html5_document` and `scrub_html5_` calls whose output is shown to other users","fix":"- Loofah: upgrade to `2.25.3` or later\n- Nokogiri: upgrade to `1.19.5` or later","status":"open","published_at":"2026-11-12T19:16:56+00:00","first_seen_at":"2026-11-12T19:40:13+00:00","triaged_at":"2026-11-12T20:54:13+00:00","updated_at":"2026-11-12T20:54:13+00:00","category":"package","confidence":0.85,"triage":{"at":"2026-11-12T20:54:13Z","model":"claude-haiku-5-5","output":{"fix":"- Loofah: upgrade to `2.25.3` or later\n- Nokogiri: upgrade to `1.19.5` or later","reach":"internet","title":"Loofah: mutation XSS in HTML5 scrubbers via unescaped attribute values","impact":"medium","summary":"Loofah's HTML5 scrubbers can emit markup that a browser parses differently, so attribute content inside allowed MathML becomes live HTML. An attacker who supplies sanitized input that other users view can run script in their browser.","audience":"developers","category":"package","nicknames":[],"who_cares":["ruby","rails","loofah","nokogiri","rails-html-sanitizer"],"confidence":0.85,"fix_status":"available","needs_auth":"unknown","worst_case":"Script runs in other users' browsers on the sanitized page","analyst_note":"","how_to_check":"- Check the Loofah version in `Gemfile.lock` for `loofah` below `2.25.3`\n- Check the Nokogiri version in `Gemfile.lock` for `nokogiri` below `1.19.5`\n- Search the code for `Loofah.html5_fragment`, `Loofah.html5_document` and `scrub_html5_` calls whose output is shown to other users","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["html4-api-only","whitewash-scrubber","jruby","rails-html-sanitizer-default-config"],"who_is_affected":"Applications that sanitize untrusted HTML with Loofah's HTML5 API and then display the result to other people are exposed, including with the default allowlist. The HTML4 API, `Loofah::Helpers.sanitize`, the `:whitewash` scrubber, rails-html-sanitizer's default configuration, and JRuby are not affected. Teams that only sanitize HTML they never show to others can skip it.","user_interaction":"yes","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"unknown"},"cost_usd":0.000859,"input_tokens":5123,"output_tokens":694,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-116':25B '-126203':14A,22A '-2026':13A,21A '-79':27B '1.19.5':93C,140C,155C,218C '2.25.3':152C,213C 'affect':122C,132C,182C,189C 'allow':53B,89C,113C 'allowlist':187C 'api':166C,193C 'applic':157C 'attack':59B 'attribut':10A,50B,99C,114C,144C 'becom':55B 'browser':46B,73B,84C,108C,125C,135C 'certain':105C 'configur':206C 'contain':104C 'content':51B 'could':79C 'cve':12A,20A 'cwe':24B,26B 'default':186C,205C 'differ':48B,87C 'display':175C 'emit':42B,80C 'escap':96C,129C,141C 'everi':124C 'fqj4':19A 'ghsa':16A 'ghsa-h6v6-rg66-fqj4':15A 'h6v6':17A 'helpers.sanitize':196C 'html':34B,57B,117C,148C,161C,202C 'html4':192C 'html5':6A,39B,77C,165C,172C 'impact':156C 'includ':183C,194C 'input':63B 'insid':52B,111C 'jrubi':208C 'live':56B,116C 'loofah':1A,23A,28B,37B,75C,151C,163C,190C,195C,212C 'loofah.html5_document':168C 'loofah.html5_fragment':167C 'markup':43B,88C,110C 'mathml':54B,106C 'method':173C 'mitig':209C 'mutat':2A,90C 'nokogiri':29B,92C,139C,154C,216C 'output':81C,103C 'packag':30B 'pars':47B,85C 'peopl':180C 'prune':127C 'rail':31B,33B,201C 'rails-html-sanit':32B,200C 'requir':150C,153C 'result':177C 'rg66':18A 'rubi':36B 'run':69B 'safari':138C 'sanit':35B,62B,159C,203C 'script':70B 'scrub':171C 'scrubber':7A,40B,78C,120C,130C,199C 'standard':149C 'strip':119C 'summari':74C 'suppli':61B 'treat':109C 'unescap':9A 'untrust':160C 'upgrad':210C,215C 'user':66B 'valu':11A,100C,145C 'view':67B 'webkit':134C 'whitewash':198C 'xss':3A,91C","nicknames":[],"mitigations":[],"who_affected":"Applications that sanitize untrusted HTML with Loofah's HTML5 API and then display the result to other people are exposed, including with the default allowlist. The HTML4 API, `Loofah::Helpers.sanitize`, the `:whitewash` scrubber, rails-html-sanitizer's default configuration, and JRuby are not affected. Teams that only sanitize HTML they never show to others can skip it.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["loofah"],"ptokens":["loofah"],"labels":["cwe116","cwe79","loofah","medium","nokogiri","package","rails","railshtmlsanitizer","ruby","rubygems"],"campaign_type":null,"search_a":"'-126203':14A,22A '-2026':13A,21A 'attribut':10A 'cve':12A,20A 'fqj4':19A 'ghsa':16A 'ghsa-h6v6-rg66-fqj4':15A 'h6v6':17A 'html5':6A 'loofah':1A,23A 'mutat':2A 'rg66':18A 'scrubber':7A 'unescap':9A 'valu':11A 'xss':3A","search_b":"'-116':25B '-79':27B 'allow':53B 'attack':59B 'attribut':50B 'becom':55B 'browser':46B,73B 'content':51B 'cwe':24B,26B 'differ':48B 'emit':42B 'html':34B,57B 'html5':39B 'input':63B 'insid':52B 'live':56B 'loofah':28B,37B 'markup':43B 'mathml':54B 'nokogiri':29B 'packag':30B 'pars':47B 'rail':31B,33B 'rails-html-sanit':32B 'rubi':36B 'run':69B 'sanit':35B,62B 'script':70B 'scrubber':40B 'suppli':61B 'user':66B 'view':67B","search_c":"'1.19.5':93C,140C,155C,218C '2.25.3':152C,213C 'affect':122C,132C,182C,189C 'allow':89C,113C 'allowlist':187C 'api':166C,193C 'applic':157C 'attribut':99C,114C,144C 'browser':84C,108C,125C,135C 'certain':105C 'configur':206C 'contain':104C 'could':79C 'default':186C,205C 'differ':87C 'display':175C 'emit':80C 'escap':96C,129C,141C 'everi':124C 'helpers.sanitize':196C 'html':117C,148C,161C,202C 'html4':192C 'html5':77C,165C,172C 'impact':156C 'includ':183C,194C 'insid':111C 'jrubi':208C 'live':116C 'loofah':75C,151C,163C,190C,195C,212C 'loofah.html5_document':168C 'loofah.html5_fragment':167C 'markup':88C,110C 'mathml':106C 'method':173C 'mitig':209C 'mutat':90C 'nokogiri':92C,139C,154C,216C 'output':81C,103C 'pars':85C 'peopl':180C 'prune':127C 'rail':201C 'rails-html-sanit':200C 'requir':150C,153C 'result':177C 'safari':138C 'sanit':159C,203C 'scrub':171C 'scrubber':78C,120C,130C,199C 'standard':149C 'strip':119C 'summari':74C 'treat':109C 'untrust':160C 'upgrad':210C,215C 'valu':100C,145C 'webkit':134C 'whitewash':198C 'xss':91C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-02T05:03:00+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-126203","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-126203","severity":null,"published_at":"2026-11-12T19:16:56+00:00","modified_at":"2026-11-12T19:16:56+00:00","first_seen_at":"2026-11-12T19:40:13+00:00","fetched_at":"2026-11-12T19:40:13+00:00","note":null},{"source":"ghsa","external_id":"GHSA-h6v6-rg66-fqj4","url":"https://github.com/advisories/GHSA-h6v6-rg66-fqj4","severity":"medium","published_at":"2026-11-12T20:52:09+00:00","modified_at":"2026-11-12T20:52:10+00:00","first_seen_at":"2026-11-12T20:53:40+00:00","fetched_at":"2026-11-12T20:58:53+00:00","note":null}],"documents":[{"id":137846,"url":"https://github.com/flavorjones/loofah/commit/7ba1e7b77e043fb7dc832ef746fcbf83137135e6","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":137847,"url":"https://github.com/flavorjones/loofah/releases/tag/v2.25.3","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: github.com"},{"id":137848,"url":"https://github.com/flavorjones/loofah/security/advisories/GHSA-h6v6-rg66-fqj4","title":"Vendor advisory: github.com","kind":"vendor","source":"nvd","publisher":"vendor","text":null,"published_at":"2026-11-02T05:03:00+00:00","relation":"advisory","confidence":null,"note":"Vendor advisory: github.com"},{"id":137849,"url":"https://github.com/sparklemotion/nokogiri/commit/635abc8d65c75d594ddf8957fbfbfd822c2c0dbd","title":"Patch: github.com","kind":"other","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":118162,"url":"https://github.com/sparklemotion/nokogiri/releases/tag/v1.19.5","title":"Release notes: github.com","kind":"release","source":"nvd","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release notes: github.com"},{"id":138466,"url":"https://api.github.com/repos/flavorjones/loofah/security-advisories/GHSA-h6v6-rg66-fqj4","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":138468,"url":"https://github.com/flavorjones/loofah/pull/324","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}