ASVS 5.0 V1.3.4 (Level 2) requires that user supplied SVG content is validated or sanitized so it contains only the tags and attributes your application needs for drawing, and no scripts, foreignObject elements or similar active content. SVG is XML that browsers treat as a document, so it can run script.
Why it matters
An avatar upload of evil.svg with an onload attribute or an embedded script element runs JavaScript when someone opens the image URL directly, and it can run under your own origin. That gives an attacker access to sessions and the page's data. SVG can also pull in external resources and entities, which leads to tracking and server side file reads when it is processed on the server.
How to implement it
Pick one of three routes, in order of safety:
- Do not accept SVG. Accept PNG or JPEG, and re-encode them.
- Rasterize the SVG on upload to PNG in a sandboxed process, and store only the PNG.
- Sanitize with an allowlist library, then serve with safe headers.
For route three, DOMPurify can run in SVG mode:
const clean = DOMPurify.sanitize(svgText, {
USE_PROFILES: { svg: true },
FORBID_TAGS: ['script', 'foreignObject', 'use', 'animate', 'set'],
FORBID_ATTR: ['style'],
});
Whatever you choose, also serve user files from a separate domain, with Content-Type: image/svg+xml, X-Content-Type-Options: nosniff and Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox. Parse server side with an XML parser that has external entities and DTDs disabled.
How to test it
Upload an SVG with onload="alert(1)", one with a script element, one with a foreignObject containing HTML, and one referencing an external image. Open the stored URL directly. No alert may fire and the dangerous elements must be gone from the stored file.
Common mistakes
- Checking the file extension or MIME type only.
- Embedding SVG inline in HTML pages without sanitizing.
- Serving uploads from the main application domain.
Where this goes wrong in practice
Teams usually discover the problem through a profile picture feature. A designer wants vector logos, so SVG is allowed, stored in a bucket and served from the main domain. The file opens as a document, and its script runs with access to cookies and local storage for that domain. Moving uploads to a separate cookieless domain is a high value fix on its own, because even an unsanitized file then has nothing to steal.
Server side processing adds a second risk. Libraries that rasterize SVG may follow external references and entities, so an uploaded file can make your server fetch internal addresses, which links this requirement to SSRF protection. Run conversion in a sandbox without network access, with time and memory limits, and treat conversion failures as rejection rather than retry.
Finally, keep a list of the SVG elements you really need. Most logo and icon use cases need paths, shapes, groups and gradients. Everything else can go.
Quick check
Why can an image file run code?
SVG is an XML document format. Browsers allow script and active elements in it when it is opened as a document.