HN
Today

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.

46
Score
12
Comments
#3
Highest Rank
20h
on Front Page
First Seen
Apr 27, 4:00 PM
Last Seen
Apr 28, 11:00 AM
Rank Over Time
338138141412161518181919191820211924

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() and image() 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.