The Woes of Sanitizing SVGs
This post dives deep into Scratch's never-ending struggle to sanitize user-generated SVGs, revealing a comical yet concerning cat-and-mouse game against an endlessly complex specification. The author meticulously details a series of XSS and HTTP leak vulnerabilities found and 'fixed' year after year, only for new bypasses to emerge. It's a sobering technical exposé on the futility of sanitization for rich, Turing-complete formats and a strong case for sandboxing.
The Lowdown
The article 'The Woes of Sanitizing SVGs' chronicles Scratch's ongoing battle against security vulnerabilities stemming from its handling of user-submitted SVGs. Since 2019, Scratch has attempted to secure its platform by building increasingly complex sanitization infrastructure, but new bypasses consistently surface.
- 2019: XSS via <script> tag was initially fixed with a regex, but bypassed due to case-sensitivity and other JS embedding methods.
- 2020: XSS via inline event handlers (CVE-2020-27428) was addressed by integrating DOMPurify.
- 2022: HTTP leak via <image> href exploited DOMPurify's limitations and was fixed by custom DOMPurify hooks.
- 2023: HTTP leak via CSS @import led to implementing a JavaScript-based CSS parser to remove dangerous imports.
- 2024: XSS via Paper.js occurred because unsanitized SVGs were passed to a library, requiring extended sanitization.
- 2025: HTTP leak via CSS url() was patched by expanding the SVG sanitization to search and remove external URLs in styles.
- 2026: HTTP leak via several bugs in previous code exposed flaws in
url()detection, including escape codes and CSS variables, leading to substantial complexity additions. - 2026: Full page restyling via long transitions (unfixed) allows attackers to arbitrarily style the entire Scratch page for extended periods.
- 2026: HTTP leak via image-set() (unfixed, disclosed after delayed response from Scratch) exploits an alternative to
url()for external requests. - 20XX: HTTP leak via new CSS features (unfixed, future vulnerability) anticipates issues with
src()andimage()from upcoming CSS specs.
The author argues that this ever-growing complexity is unsustainable and proposes an alternative: sandboxing SVGs within an iframe with a strict Content Security Policy. This approach leverages the browser's built-in security mechanisms and prevents SVGs from affecting the main document. The article concludes by noting a recent bug discovered by Claude Opus 4.6 involving CSS nesting, which further underscores the futility of trying to perfectly parse and sanitize SVGs in userland.
The Gossip
The Perils of Permissive Parsing
Commenters question the fundamental design choice requiring Scratch to inline SVGs directly for measurements, which forces them into this endless security cat-and-mouse game. There's a strong sentiment that relying on sanitization for a format as rich and powerful as SVG is inherently flawed, with many advocating for the sandboxing approach showcased in the article as a more robust solution.
Seeking Simpler Standards: The Call for 'SVG-ES'
Many in the discussion expressed a desire for a simplified, constrained subset of SVG, perhaps branded as 'SVG-ES' (like OpenGL ES), that would allow for basic vector graphics without the security overhead of script execution or external resource loading. They acknowledge the challenges of standardizing such a subset and maintaining compatibility with existing design tools.
The Broader Impact: Why Google Slides Lacks SVG
The discussion highlights that Scratch's extensive struggles are not unique, with one commenter pointing out that even large platforms like Google Slides avoid comprehensive SVG support due to these same security and complexity concerns. This underscores the widespread nature of the challenging problem of safely handling user-provided, dynamic vector graphics.