The Woes of Sanitizing SVGs

· coding security · Source ↗

TLDR

  • Scratch’s seven-year whack-a-mole history of SVG sanitization failures shows that parsing attacker-controlled SVGs into the live DOM is structurally unsafe.

Key Takeaways

  • Root cause: Scratch appends user-submitted SVGs directly into the main document to measure bounding boxes, making any sanitization approach fragile by design.
  • CVE chain runs 2019-2026: script tags, case-sensitive regex bypass, <image href> HTTP leak, CSS @import, Paper.js XSS, url() leaks, image-set() leaks – each fix introduced new bypass surface.
  • DOMPurify explicitly declines to block HTTP leaks, stating reliable blocking is not feasible; Scratch had to bolt on custom hooks for every new CSS vector.
  • A still-unpatched 2026 bug allows arbitrary page restyling via long CSS transitions, enabling phishing overlays and hidden report buttons on real scratch.mit.edu.
  • An image-set() HTTP leak disclosed to Scratch in 2025 remains unpatched and is disclosed here after the 6-month window lapsed.

Hacker News Comment Review

  • Commenters converged on a whitelist-subset approach as the practical alternative: most real SVGs are just paths and fills; blocking the “clever dangerous” subset would cover the attack surface without endless patch cycles.
  • The Google Slides angle surfaced as concrete industry evidence: nearly 15 years of user requests for SVG import have gone unimplemented, implying large teams have assessed the sanitization problem and rejected it entirely.
  • TinyVG was floated as a safe alternative format, but commenters noted missing animation support and low ecosystem traction as blockers to any meaningful adoption.

Notable Comments

  • @spankalee: Google Slides still has no SVG support despite a ~15-year-old feature request – strong implicit evidence that sanitization is considered unsolvable at scale.
  • @ikkun: endorses TinyVG as a safer vector format but flags missing animation support as a real gap.

Original | Discuss on HN