The woes of sanitizing SVGs

Efforts to safely handle user-supplied SVG files are proving surprisingly complex, since SVG is effectively a full markup language with scripting, CSS, external resource loading, and other HTML-like attack surfaces. Commenters describe real-world vulnerabilities, such as XSS in Scratch and the lack of SVG support in tools like Google Slides, and argue that regex-based sanitization or ad hoc filters are fundamentally brittle. Many advocate for stronger, standardized approaches—such as strict whitelists, CSP, sandboxed iframes, or a formally defined “safe” SVG subset or new vector format—to get the benefits of scalable graphics without opening serious security holes.

Nature of SVG and Risks

  • Commenters stress that SVG is a markup language, not a simple image format; it’s as dangerous as HTML when untrusted.
  • Main hazards: embedded <script>, event-handler attributes, <foreignObject> with HTML, external URLs in attributes/CSS, <image>/feImage, DTD and namespace tricks.
  • Browsers already treat the same SVG differently depending on context: <img> disables scripts/external loads, while inline and <object> can execute them.
  • Because the same file can be used as both “image” and “document,” simply “allow SVG uploads” is risky.

Subset and New-Format Proposals

  • Many suggest supporting only a restricted SVG subset that covers common “paths + fills” use cases.
  • Existing or proposed subsets/formats are mentioned: SVG Tiny, SVG Tiny PS, SVG Native, BIMI profiles, Android’s vector format, TinyVG, and ideas like “SVG-ES” or “SSVG.”
  • Trade‑off: security and simpler tooling vs losing features such as SMIL animation, filters, and drop shadows. Some see that loss as acceptable for wide adoption; others do not.

Real-World Cases and Tooling

  • Scratch’s history illustrates the pitfalls: initial XSS via <script>, then repeated sanitizer bypasses (including regex-based filtering).
  • Scratch inlines SVGs so it can call getBBox() because many input files have bad viewboxes.
  • There are references to SVG sanitization libraries and to the browser HTML Sanitizer API, which allows a limited SVG subset but bans style by default.

Security Mitigations Discussed

  • Strong preference for CSP over ever-more-complex sanitizers: script-src 'none', sandboxing, and applying CSP directly via <meta http-equiv> in documents or iframes.
  • Iframe sandboxing plus strict CSP is seen as robust but underused, partly due to poor docs and integration friction with modern frameworks.
  • Some propose blocking any http(s) URLs in attributes or constraining SVG by headers like Content-Security-Policy and Sec-Fetch-*.

Embedding Modes and API Ideas

  • Frequent wish for a simple, declarative “safe mode”:
    • Attributes like sandbox or exec="false" on <svg>.
    • Type flags (<img type="ssvg">) or special SVG versions/namespaces that guarantee no scripts or external fetches.
  • Others argue that <img src="file.svg"> already provides a mostly-correct safe image behavior, but lacks dynamic styling (e.g., CSS variables) and DOM interactivity.

Broader Reflections

  • Several see SVG’s scripting and HTML-like complexity as “overreach” when most users just want crisp logos.
  • Others note SVG’s origins as a richer, potentially Flash-like interactive medium, which explains (but doesn’t excuse) today’s security headaches.