An SVG can look like an ordinary logo while carrying JavaScript that becomes active when the file is inserted inline, opened directly, or embedded with a permissive element. The painful part is that removing one visible <script> block does not prove the file is passive.
Use this fast rule:
Treat every untrusted SVG as active document input. Parse it as XML, allow only the elements and attributes your product needs, remove all script-capable paths, serialize it, and inspect the result again. If you only need the appearance, rasterize it instead.
For a broader intake workflow, use the SVG upload security checklist. If you only need a fresh vector based on a trusted bitmap, convert the image to SVG instead of reusing unknown markup.

Can SVG files contain JavaScript?
Yes. SVG is XML-based document markup, not a passive pixel format. It can include a <script> element and may expose other execution paths through event attributes, URLs, embedded HTML, CSS, animation, and linked resources. Execution depends on how the browser receives and embeds the file.
SVG JavaScript is executable browser code carried inside or referenced by an SVG document. A minimal example is easy to spot:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<script>{`/* executable code */`}</script>
<circle cx="50" cy="50" r="40" fill="#2563eb" />
</svg>
The circle is valid artwork. The script is active document behavior. A thumbnail, extension check, or visual review sees the circle and may never reveal the code.
MDN documents the SVG script element and notes that it adds scripts to an SVG document. OWASP's XSS prevention guidance explains why dangerous contexts and event handlers require strict handling. The practical consequence is simple: do not give uploaded SVG the trust you would give PNG or JPEG pixels.
When can JavaScript inside SVG execute?
JavaScript is most concerning when untrusted SVG becomes part of a script-capable document: inline markup, direct navigation, object, embed, or some iframe configurations. An SVG loaded through img is generally more restricted, but that safer rendering context does not clean the underlying file.
| SVG use | Relative risk | Safer decision |
|---|---|---|
| Inline markup in application HTML | High | Never inject untrusted raw SVG |
object or embed | High | Avoid for uploads; use an isolated preview |
| Direct file URL | Context-dependent | Isolate origin and apply restrictive headers |
img source | Lower | Prefer for sanitized SVG display |
| Sandboxed raster preview | Lowest for display | Use when vector editing is unnecessary |
Embedding is a security boundary, not a sanitizer. A file displayed through img today may be downloaded, opened in a browser tab, pasted into a CMS, or inlined by a build tool tomorrow. The SVG Content Security Policy guide explains the response headers that reduce damage when stored SVG must be served.
Is removing the SVG script element enough?
No. Removing <script> closes one obvious path, but executable behavior can survive in attributes and referenced content. A safe policy must inspect the whole parsed document, including namespaced attributes, URL values, style rules, animation, and embedded HTML.
Common paths to account for include:
- event attributes such as
onload,onclick,onerror,onbegin, and any normalized attribute name beginning withon; - dangerous or unexpected schemes in
href,xlink:href, and other URL-bearing attributes; - HTML carried by
foreignObject; - CSS imports, external URLs, and script-capable edge cases inside
<style>; - remote documents or resources referenced by
use,image, filters, fonts, or animation; - confusing namespaces or parser disagreements that turn apparently inert markup into active content.
Do not respond by making a longer blacklist. Define the small subset of SVG that your feature truly needs—often paths, basic shapes, groups, transforms, paint, gradients, masks, clipping, and accessibility metadata—and reject everything outside it. For the attribute-specific layer, the SVG event handler security guide shows why a normalized on* rule is stronger than a short list.
What is the safest way to remove JavaScript from SVG?
Use an XML-aware parser and a maintained sanitizer configured for SVG, then apply a product-specific allowlist. Perform the work on the server before storage, reparse the serialized result, and reject the file if the output still contains forbidden elements, attributes, schemes, namespaces, or external loads.
Use this sequence:
- Limit the input. Enforce byte size, decompression, element count, nesting depth, path complexity, and processing time limits.
- Parse as XML. Reject malformed files,
DOCTYPE, entity declarations, and ambiguous parser output. - Allow known SVG structure. Keep only the elements and attributes required by your editor or renderer.
- Remove execution paths. Drop
script, everyon*attribute, embedded HTML, unsafe URLs, and unexpected namespaces. - Constrain references. Prefer same-document fragments such as
url(#gradient)and reject remote resources unless explicitly required. - Serialize and reparse. Validate the exact bytes you will store or serve rather than trusting the in-memory intermediate.
- Render in isolation. Use a separate origin or sandbox, restrictive Content Security Policy, and no application cookies.
- Regression-test real artwork. Confirm that gradients, masks, clipping paths, symbols, and accessibility labels still work.
DOMPurify supports SVG sanitization, but its configuration and execution environment matter. Its documentation also warns that modifying sanitized markup afterward can void the protection. Pin updates, test your chosen allowlist, and never treat a short demo snippet as a complete upload security system.
Why should you avoid regex for SVG JavaScript removal?
Regex cannot reliably model XML parsing, namespace resolution, character references, quoting, case normalization, CSS, and browser interpretation. It may miss an encoded payload, damage valid path or metadata content, or create output that the browser parses differently from the filter.
A search for <script is useful as a warning, not as proof of safety. The same is true for scanning the raw string for javascript: or onload=. These checks cannot answer whether an attribute was namespaced, encoded, reconstructed after another transform, or hidden in a structure the filter did not expect.
Use raw-text checks only as a cheap early rejection layer. The deciding inspection must operate on a parsed tree and normalized values. If the parser and browser may disagree, reject the file rather than betting the application origin on an interpretation.
How do you check an SVG for hidden JavaScript?
Check structure and behavior separately. A structural test should walk the parsed tree and fail on forbidden constructs. A behavioral test should render the sanitized file in an isolated harness while observing script effects, network requests, navigation, DOM changes, console messages, and excessive resource use.
Your test fixtures should include at least:
<svg><script>{`/* test marker */`}</script></svg>
<svg onload="testMarker()"></svg>
<svg><a href="javascript:testMarker()"><text>Link</text></a></svg>
<svg><foreignObject><div xmlns="http://www.w3.org/1999/xhtml">HTML</div></foreignObject></svg>
<svg><use href="https://untrusted.example/file.svg#shape" /></svg>
For every fixture, require one of two outcomes: the upload is rejected, or the stored result contains only the safe artwork. Then reparse that result and assert that:
- no
script,foreignObject, or unsupported active element remains; - no normalized attribute name begins with
on; - every URL has an allowed scheme and destination;
- every namespace is expected;
- CSS contains no disallowed import or external load;
- the isolated render makes no unexpected request or navigation.
Keep a second regression set of legitimate SVGs. Security that silently ruins gradients, masks, or text will eventually be bypassed by users or disabled by developers.
Should you sanitize SVG or convert it to PNG?
Sanitize when users genuinely need editable vector paths, scalable geometry, or SVG-specific styling. Convert to PNG or WebP when they only need a preview, avatar, thumbnail, or flattened visual. Reject the upload when neither path can be performed safely.
Use this decision rule:
- Need editable vectors? Sanitize server-side, validate again, and isolate delivery.
- Need only the visible result? Rasterize inside a restricted service and display the passive output.
- Need to build a clean vector from a trusted image? Use SVG Genie's image-to-SVG converter.
- Cannot safely parse or render the file? Reject it with a useful error instead of previewing unknown markup.
The easiest secure architecture is often to keep an original upload quarantined, generate a raster preview, and expose only a sanitized derivative for vector editing. That separates what the user supplied from what your application trusts.
What headers help when serving uploaded SVG?
Serve uploaded SVG from a separate, cookieless origin when possible and use restrictive browser headers as defense in depth. Headers do not repair malicious markup, but they reduce the consequences of a sanitizer failure or a file being opened directly.
Consider:
- a strict
Content-Security-Policythat blocks scripts and unnecessary connections; X-Content-Type-Options: nosniff;- an accurate
Content-Type: image/svg+xmlonly after validation; Content-Disposition: attachmentwhen inline display is unnecessary;- no authenticated application cookies on the asset origin;
- a sandboxed iframe for preview workflows that require document rendering.
Keep the layers independent: validation decides whether the file is structurally acceptable, sanitization removes unsupported content, isolation limits privileges, and headers constrain browser behavior. One layer failing should not hand uploaded XML the keys to the main application.
Frequently asked questions
Can SVG files contain JavaScript?
Yes. SVG can contain script elements and other active features. Whether the code runs depends on the rendering context, but untrusted SVG should always be treated as active document input.
Is deleting the SVG script element enough?
No. Event handlers, unsafe URLs, embedded HTML, CSS, animation, and external references may remain. Enforce a positive SVG allowlist across the whole parsed document.
Can JavaScript run when SVG is loaded with an img tag?
Browsers generally restrict scripting in SVG loaded as an image, so img is safer than inline SVG or object. Still sanitize the file because it can later be reused or opened in another context.
How do I check an SVG for JavaScript?
Parse it as XML and inspect every element, attribute, namespace, URL, style rule, and reference. Reparse the cleaned output and behavior-test it in an isolated browser harness.
What is the safest way to display an untrusted SVG?
If vector editing is unnecessary, rasterize it in a sandbox and show a PNG or WebP preview. Otherwise sanitize on the server, isolate delivery, apply restrictive headers, and never inject raw upload markup into application HTML.
Create your own SVG graphics with AI
Describe what you need, get a production-ready vector in seconds. No design skills required.
About This Article
This article was written by SVG Genie Team based on hands-on testing with SVG Genie’s tools and years of experience in vector design and web graphics. All recommendations reflect real-world usage and are reviewed by the SVG Genie editorial team for accuracy.
About the Author
SVG Genie Team
SVG Design Expert & Technical Writer at SVG Genie
SVG Genie Team is a vector design specialist and technical writer at SVG Genie with years of hands-on experience in SVG tooling, AI-assisted design workflows, and web graphics optimization. Their work focuses on making professional vector design accessible to everyone.
More articles by SVG Genie Teamarrow_forward