{"id":"TECH-202610-svg-sanitizer-bypasses-six-of-eight-popular-svg-sanitizer-li","kind":"technique","aliases":[],"related":[],"title":"SVG sanitizer bypasses: six of eight popular SVG sanitizer libraries let uploaded SVGs run JavaScript (XSS)","description":null,"summary":"PortSwigger Research (Gareth Heyes, 2026-10-27) bypassed 6 of 8 popular SVG sanitizers, so apps that accept SVG uploads and rely on them can serve stored XSS. Affected: mattkrick/sanitize-svg (XHTML namespace switch, foreignobject case bug, nested svg onload, XSLT), Borewit/svg-sanitizer (animate/set of href to javascript: URL), bgalek/safe-svg and alnorris/SVG-Sanitizer (xml-stylesheet processing instruction pointing to a data: URL XSLT stylesheet), cloudflare/svg-hush, jams2/py-svg-hush and bgalek/safe-svg (Safari <use> importing an uploaded GIF/image as SVG). Also shown: Firefox runs an XSLT stylesheet supplied in a Link response header even when the body is harmless XML. DOMPurify and darylldoyle/svg-sanitizer held up. The author says two unnamed popular applications were exploited. Proof of concept only; no in-the-wild use reported. Fix status per library: unknown.","severity":"medium","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"sanitize-svg","fixed":[],"vendor":"mattkrick","ecosystem":"npm"},{"name":"svg-sanitizer","fixed":[],"vendor":"Borewit","ecosystem":"npm"},{"name":"safe-svg","fixed":[],"vendor":"bgalek"},{"name":"SVG-Sanitizer","fixed":[],"vendor":"alnorris"},{"name":"svg-hush","fixed":[],"vendor":"Cloudflare","ecosystem":"crates.io"},{"name":"py-svg-hush","fixed":[],"vendor":"jams2","ecosystem":"PyPI"}],"ecosystems":[],"tags":["early-warning","technique"],"not_affected_if":[],"how_to_check":"Check if your app accepts SVG uploads and sanitizes them with sanitize-svg (mattkrick), svg-sanitizer (Borewit), safe-svg (bgalek), SVG-Sanitizer (alnorris), svg-hush (Cloudflare, Rust) or py-svg-hush; look in stored SVGs for xml-stylesheet processing instructions with data: URLs, <animate>/<set> on href, elements with an XHTML xmlns, and <use> pointing at uploaded image files","fix":"Switch SVG sanitizing to DOMPurify (SVG profile) or darylldoyle/svg-sanitizer, or watch for fixed releases of the affected libraries; serve user-uploaded SVGs from a separate sandbox domain with Content-Security-Policy: sandbox / script-src 'none' and Content-Disposition: attachment, or convert them to raster images; strip xml-stylesheet processing instructions","status":"open","published_at":null,"first_seen_at":"2026-10-27T15:07:17+00:00","triaged_at":"2026-10-27T15:07:17+00:00","updated_at":"2026-10-27T15:07:17+00:00","category":"package","confidence":null,"triage":null,"analyst_status":"done","analyst_note":null,"search":"'-10':58B '-202610':18A '-27':59B '2026':57B '6':61B '8':63B 'accept':70B 'affect':81B 'alnorris/svg-sanitizer':102B 'also':126B 'animate/set':94B 'app':68B 'applic':157B 'author':152B 'bgalek/safe-svg':100B,118B 'bodi':142B 'borewit/svg-sanitizer':93B 'bug':88B 'bypass':3A,60B 'bypasses':22A 'case':87B 'cloudflare/svg-hush':115B 'concept':162B 'darylldoyle/svg-sanitizer':148B 'data':111B 'dompurifi':146B 'earli':50B 'early-warn':49B 'eight':6A,25A 'even':139B 'exploit':159B 'firefox':128B 'fix':171B 'foreignobject':86B 'gareth':55B 'gif/image':123B 'harmless':144B 'header':138B 'held':149B 'hey':56B 'href':96B 'hush':44A,48A 'import':120B 'in-the-wild':165B 'instruct':107B 'jams2/py-svg-hush':116B 'javascript':15A,98B 'let':11A 'li':29A 'librari':10A,174B 'link':136B 'mattkrick/sanitize-svg':82B 'namespac':84B 'nest':89B 'of':24A 'onload':91B 'per':173B 'point':108B 'popular':7A,26A,64B,156B 'portswigg':53B 'process':106B 'proof':160B 'py':46A 'py-svg-hush':45A 'reli':74B 'report':170B 'research':54B 'respons':137B 'run':14A,129B 'safari':119B 'safe':37A 'safe-svg':36A 'sanit':2A,9A,66B 'sanitize':31A 'sanitize-svg':30A 'sanitizer':21A,28A,35A,41A 'say':153B 'serv':78B 'shown':127B 'six':4A,23A 'status':172B 'store':79B 'stylesheet':105B,114B,132B 'suppli':133B 'svg':1A,8A,20A,27A,32A,34A,38A,40A,43A,47A,65B,71B,90B,125B 'svg-hush':42A 'svg-sanitizer':33A,39A 'svg-sanitizer-bypasses-six-of-eight-popular-svg-sanitizer-li':19A 'svgs':13A 'switch':85B 'tech':17A 'techniqu':52B 'two':154B 'unknown':175B 'unnam':155B 'upload':12A,72B,122B 'url':99B,112B 'use':169B 'warn':51B 'wild':168B 'xhtml':83B 'xml':104B,145B 'xml-stylesheet':103B 'xslt':92B,113B,131B 'xss':16A,80B","nicknames":[],"mitigations":[],"who_affected":null,"tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-27T14:29:26+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"analyst","external_id":"TECH-202610-svg-sanitizer-bypasses-six-of-eight-popular-svg-sanitizer-li","url":null,"severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-27T15:07:17+00:00","fetched_at":"2026-10-27T15:07:17+00:00","note":null}],"documents":[{"id":6579,"url":"https://portswigger.net/research/scalable-vector-grief","title":"PortSwigger Research: Scalable Vector Grief","kind":"blog","source":"blog","text":"Scalable Vector Grief\n\nI tested eight popular SVG sanitizers and bypassed six of them. In this post, I'll show you how a response header can run JavaScript in Firefox even when the response body is completely harmless XML.","published_at":"2026-10-27T14:29:26+00:00","relation":"describes","confidence":null,"note":null}],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}