What is SVG XSS?

The upload that looks like an image and parses like a document.

By Ihor Havrysh ยท Last reviewed July 2026

Eaglepedia mascot

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
The same SVG served three ways: inside an image tag scripts do not run, at its own address or inlined they do
Applications tend to acquire the dangerous path by accident, through a download link, a preview feature or a direct-serving configuration.

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.

Frequently asked questions

Because they are fundamentally different kinds of file. A JPEG is compressed pixel data, and a browser decodes it into an image. An SVG is an XML document describing shapes, and the browser parses it in much the same way it parses HTML. The SVG specification includes script elements and event handler attributes as legitimate features, so a browser rendering one is executing a document rather than displaying a picture.

Enormously, and this is the most useful thing to understand. An SVG referenced inside an img tag is rendered without script execution, which is why many applications never encounter a problem. The risk appears when the file is served as its own document, so that navigating to its URL renders it directly, or when its markup is inlined into a page. Same file, entirely different outcome.

No. SVG is XML text and has no binary signature to check, so content-based type detection has very little to work with. A file that begins with an XML declaration and an svg element is a valid SVG regardless of what else it contains. The script is not an anomaly in the format, it is a documented feature of it.

Stripping means finding and removing the parts you consider unsafe, which requires your list of unsafe things to be complete. Rebuilding means parsing the file and writing a new one containing only the elements and attributes you have chosen to allow, so anything unrecognised is absent by default rather than by detection. The second approach is safer because it fails towards safety.

It is a legitimate choice and a common one, particularly if your users would be equally well served by PNG. If you do accept SVG, because the scalability genuinely matters for logos or diagrams, then treat it as an active document: sanitise it against an allowlist, serve it from a separate origin, set a restrictive content security policy and force it to download rather than render where you can.
Ihor Havrysh - Software Engineer at Red Eagle Tech

About the author

Ihor Havrysh

Software Engineer

Software Engineer at Red Eagle Tech with expertise in cybersecurity, Power BI, and modern software architecture. I specialise in building secure, scalable solutions and helping businesses navigate complex technical challenges with practical, actionable insights.

Read more about Ihor

Discovery call

A friendly 15-minute video call with Kat to understand your needs. No preparation needed.

  • Discuss your project
  • Get honest advice
  • No obligation
Kat Korson, Founder of Red Eagle Tech

Kat Korson

Founder & Technical Director

Our team has 10+ years delivering software solutions for growing businesses across the UK.

Send us a message

Your information is secure. See our privacy policy.

Find us