SVG XSS is cross-site scripting delivered through a Scalable Vector Graphics file. SVG is an XML document rather than a grid of pixels, and the format permits script elements and event handlers, so an uploaded image can execute code when a browser renders it directly.
SVG is a document that happens to draw
Almost every image format an application accepts is a container for pixel data. The file describes colours, the decoder turns them into a picture, and there is nowhere in that process for behaviour to live.
SVG works the other way round. It is XML describing shapes, paths, text and transformations, and the browser parses that markup much as it parses HTML. That is what makes it valuable: the output scales perfectly because the browser draws it rather than resizing a bitmap.
It also means the format supports things a picture format has no reason to support. Scripting, event handlers, external references, embedded styles and animation are all part of what SVG is, documented in the specification and implemented by every browser. None of this is a flaw. It is a document format doing document things, and the mismatch only appears when an application files it mentally alongside PNG and JPEG.
The consequence is direct: when a browser renders an SVG as a document, any script inside it runs in the context of whichever origin served it. If that is your application's origin, the script has access to whatever a script on your pages would have.
How it is served changes everything
This is the part worth getting straight, because it explains why plenty of applications accept SVG uploads for years without incident.
- Referenced in an image tag: the browser renders it in a restricted mode where scripts do not execute. This is the common case, and it is safe by default
- Served as its own document: navigating directly to the file renders it as a document, and scripts run. This is the dangerous case, and it happens whenever a user can open an uploaded file at its own URL
- Inlined into your markup: the SVG becomes part of your page, and anything in it is part of your page too
So the same stored file can be entirely harmless or a live cross-site scripting vector depending on how somebody reaches it. Applications tend to acquire the dangerous path by accident: a download link, a preview feature, an admin tool that opens the original, or a content delivery configuration that serves stored files directly.
Validation is little help here. Because SVG is text, there is no binary signature to test, so checking magic bytes has almost nothing to work with. A file starting with an XML declaration and an svg root element is a valid SVG, whatever else it contains.
Four controls that contain it
Because the risk depends on rendering context as much as on file content, the effective controls come in pairs: change what the file contains, and change what it could reach.
- Rebuild against an allowlist. Parse the SVG and write a new one containing only the elements and attributes you have decided to permit, the approach OWASP recommends for untrusted markup. Everything else is absent because it was never copied across, rather than because you spotted it. This fails towards safety, which stripping does not
- Serve user content from a separate origin. A dedicated domain for uploads means a script that does run has no access to sessions or storage belonging to your application. This single change downgrades most of the impact
- Force download rather than render. Where users only need to retrieve the file, a content disposition header that makes it an attachment stops the browser treating it as a document at all
- Apply a restrictive content security policy on whatever origin serves uploads, so inline script has no permission to execute even if something survives the rebuild
Rebuilding is the same principle that content disarm and reconstruction applies to documents, and SVG is a clean illustration of why it works. You are not trying to enumerate every way a script could be smuggled into XML, a list nobody can complete. You are deciding which elements draw shapes, keeping those and discarding the rest.
Declining SVG uploads altogether remains a perfectly reasonable answer where PNG would serve your users equally well. The formats are not interchangeable for logos and diagrams, so if scalability genuinely matters, accept it deliberately and put the four controls above around it.
Rebuilding beats detecting, for documents as well as images. The Red Eagle Tech CDR API reconstructs uploaded documents from the components that carry legitimate content, so active content is absent by default rather than by detection. Published per-document pricing, and you can be running in minutes.