Skip to content
Tech News
← Back to articles

The Woes of Sanitizing SVGs

read original get SVG Cleaning Kit → more articles
Why This Matters

The article highlights ongoing security challenges in sanitizing SVG files within platforms like Scratch, exposing vulnerabilities such as XSS and arbitrary code execution. This underscores the importance for the tech industry to develop more robust, future-proof methods for handling user-generated SVG content to protect users and maintain platform integrity.

Key Takeaways

2026-04-11 on muffin.ink

Scratch has a long history of SVG-related vulnerabilities. The source of these is that Scratch parses user-generated (ie. attacker-controlled) content into an <svg> element and appends it into the main document for various operations (eg. measuring SVG bounding box in a more reliable way than viewbox or width/height).

No matter how briefly the SVG remains in the main document, this is an inherently unsafe operation. Scratch's approach to making this safe has been to build increasingly complex infrastructure around parsing the SVG and the markup within to remove dangerous parts.

I think Scratch's approach to SVG sanitization is doomed. To explain, we have to take a trip through the history of SVG sanitization in Scratch to see how well it has worked so far.

2019: XSS via <script> tag

In 2019, a few months after the initial release of Scratch 3, Scratch discovered that SVGs can contain <script> tags that Scratch would cause to be executed when the SVG loads. This is known as an XSS.

In Scratch terms, an XSS allows an attacker to take actions on behalf of anyone that loads their project. For example, the attacker can post comments, delete projects, or otherwise try to take over the victim's account. In Scratch Desktop, XSS is elevated to arbitrary code execution because Scratch Desktop enables Electron's dangerous Node.js integration feature. (TurboWarp Desktop has not enabled that feature since v0.2.0 from March 2021)

Example from Scratch's test suite:

<! DOCTYPE svg PUBLIC " -//W3C//DTD SVG 1.1//EN " " http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd " > < svg version = " 1.1 " xmlns = " http://www.w3.org/2000/svg " > < circle cx = " 250 " cy = " 250 " r = " 50 " fill = " red " /> < script type = " text/javascript " > <![CDATA[ alert('from the svg!') ]]> </ script > </ svg >

This was fixed by using a regular expression to remove script tags.

... continue reading