A logo upload should not be able to make your server read a local file or contact another host. Yet that can happen when an application treats SVG as an image while its backend treats the same file as unrestricted XML.
Use this fast rule:
Reject SVG files containing DOCTYPE or ENTITY, disable DTD and external entity processing in the XML parser, cap file size and document complexity, and only then run SVG sanitization.
That order matters. A browser-focused sanitizer cannot undo a server-side entity request that already happened during XML parsing. For the browser threat model, pair this guide with the SVG XSS sanitization checklist. For the broader intake workflow, use the SVG upload security checklist.

Can an SVG file cause an XXE attack?
Yes. SVG is an XML-based format, so an unsafe XML parser may process a Document Type Definition (DTD) and resolve external entities before the application validates the artwork. Depending on the parser, configuration, network access, and error handling, this can expose files, trigger server-side requests, consume resources, or leak data through errors.
SVG XXE is an XML External Entity vulnerability triggered when a server parses attacker-controlled SVG with DTD or external entity resolution enabled. It is a backend parsing problem, not simply a browser rendering problem.
A deliberately simplified suspicious file looks like this:
<?xml version="1.0"?>
<!DOCTYPE svg [
<!ENTITY probe SYSTEM "file:///path/to/harmless-test-marker.txt">
]>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 30">
<text x="5" y="20">&probe;</text>
</svg>
Do not run unknown samples against production. The useful lesson is structural: if the parser tries to replace &probe;, it has already crossed a boundary that ordinary logo processing does not need.
Authoritative references:
- OWASP XML External Entity Prevention Cheat Sheet
- OWASP XML Security Cheat Sheet
- W3C SVG 2 specification
- CWE-611: Improper Restriction of XML External Entity Reference
Why is SVG sanitization alone not enough for XXE?
SVG sanitization usually removes browser-facing features after markup has become a document or DOM. XXE can happen earlier, during server-side XML parsing. If entity resolution performs a file read or network request at that stage, removing the resulting node later does not reverse the side effect.
Think of the controls as two separate gates:
| Gate | Stops | Required controls |
|---|---|---|
| Safe XML parsing | DTD/entity expansion, external fetches, parser exhaustion | Disable DTDs and external entities; set size, depth, node, time, and memory limits |
| SVG sanitization | Scripts, event handlers, embedded HTML, unsafe URLs, remote resources | SVG-specific element, attribute, namespace, and URL allowlists |
You need both. An XML parser can be safe from XXE while still preserving <script> or onload. An SVG sanitizer can remove those browser threats while receiving a DOM that was parsed with dangerous entity settings.
The SVG external reference security guide covers URLs inside the SVG document. XXE is different because the XML parser itself may resolve a resource while building that document.
What is the safest way to parse an uploaded SVG?
The safest parser policy is to reject DTD-bearing input, disable external entity and network resolution, avoid XInclude unless explicitly required, and impose strict resource limits before inspecting SVG elements. Choose a library with documented secure settings and verify its behavior with tests rather than trusting a default.
Use this sequence:
- Accept the upload as untrusted bytes, not as a trusted image object.
- Enforce a small maximum byte size before parsing.
- Confirm the expected media type and inspect the actual content; an extension is not proof.
- Reject
DOCTYPEandENTITYdeclarations as an early policy check. - Parse with DTD loading, entity substitution, external entities, network access, and XInclude disabled.
- Enforce maximum depth, nodes, attributes, text length, processing time, and memory.
- Sanitize the parsed SVG with a narrow allowlist.
- Serialize and reparse under the same safe settings, then assert the structure again.
- Render only the sanitized copy, preferably with
<img>or as a raster preview. - Store originals privately or offer them as attachment downloads when retention is necessary.
If your goal is to create a clean vector rather than preserve arbitrary uploaded XML, the easier route is to rebuild the artwork with Image to SVG, inspect it in the SVG editor, and keep the generated file within a controlled pipeline.
Which parser settings should developers verify?
Verify behavior, not option names. XML security switches vary by language, library, and version, and some APIs expose several overlapping controls. Your tests should prove that DTDs are rejected, external resources are never fetched, entities are not substituted, and resource-heavy documents terminate quickly.
Use this implementation checklist:
- DTD processing is prohibited rather than merely ignored after expansion.
- General and parameter external entities are disabled.
- External schema and stylesheet access is disabled if those processors exist.
- XInclude is disabled unless the product has a reviewed requirement for it.
- The parser cannot access the network.
- Entity substitution is disabled.
- Upload byte size is checked before parsing.
- Document depth, node count, attribute count, and text length are capped.
- Parser errors do not echo local file contents or secrets.
- The XML library and its transitive dependencies receive security updates.
Do not copy a configuration snippet for a different parser version and assume the job is done. OWASP maintains language-specific guidance, but a regression test is the final proof for your exact runtime.
Does removing DOCTYPE with a regex prevent SVG XXE?
No. A regex is useful only as an early rejection signal. It is not an XML parser, can be bypassed by encoding and syntax variations, may run after another component has already parsed the file, and does nothing to enforce network, memory, depth, or time limits.
The better policy is intentionally redundant:
- reject obvious DTD/entity declarations before parsing;
- configure the parser so it cannot resolve them even if the precheck misses one;
- isolate the parsing service from sensitive files and internal networks;
- test for zero outbound requests;
- sanitize the SVG document after safe parsing.
Each layer catches a different failure mode.
How do you prevent XML expansion denial of service?
Disable entity declarations and substitution, then impose hard limits on document size and complexity. Entity expansion is one exhaustion path, but a deeply nested or enormous SVG can also consume CPU and memory without external resources. Treat parser limits and render-cost limits as separate controls.
| Limit | Why it matters | Product decision |
|---|---|---|
| Upload bytes | Stops oversized input before allocation-heavy parsing | Set from real customer files, then keep the smallest workable ceiling |
| XML depth | Stops pathological nesting | Ordinary artwork rarely needs extreme depth |
| Element/node count | Bounds tree construction and later sanitization | Reject or simplify unusually complex files |
| Attribute/text length | Stops giant values hidden in small node counts | Cap individual and total text |
| Parse timeout/memory | Contains library or edge-case failures | Enforce outside the parser when necessary |
| Render dimensions/cost | Prevents expensive filters and huge canvases | Validate after safe parsing |
The SVG filter security guide covers render-cost attacks that remain after XML parsing succeeds. Optimization is not a security boundary; run the SVG optimizer only after validation and sanitization.
How should you test an SVG upload parser for XXE?
Build a small fixture suite and run it in an isolated environment with network observation. A passing test rejects DTD-bearing documents before entity resolution, creates no outbound request, exposes no local-file marker in output or logs, and stops expansion-heavy or deeply nested files within defined resource limits.
Include at least these fixtures:
- a normal path-only SVG that must pass;
- an SVG with an internal entity declaration that must fail;
- an SVG with a harmless external file marker that must fail without reading it;
- an SVG whose external entity points to a controlled local HTTP listener that must produce zero requests;
- an XInclude sample that must fail when XInclude is unsupported;
- an entity-expansion sample that must terminate within the limit;
- a deeply nested SVG that must hit the depth limit;
- a sanitized SVG containing scripts, event handlers, or remote URLs that must fail the second security gate.
Run these tests when the parser library, sanitizer, framework, or upload service changes. Also inspect logs: a safe HTTP response is not enough if an exception message quietly captured sensitive data.
What is the best production policy for user-uploaded SVG?
For ordinary logos, avatars, icons, and marketplace artwork, reject DTDs and entities, parse without external capabilities, sanitize to a narrow SVG subset, and generate a raster preview. Serve cleaned SVG only when vector output is necessary, and keep it isolated from the main application origin when practical.
The fastest decision rule is:
- Your own source-controlled SVG: review it like code and keep the toolchain patched.
- A client or editor upload: parse safely, sanitize, and render the cleaned copy with
<img>. - A public anonymous upload: prefer a raster preview and isolate processing.
- A product that does not need SVG internals: convert to pixels and avoid XML processing entirely.
For delivery controls after processing, use the SVG Content Security Policy headers guide. CSP reduces browser impact, but it cannot protect the server-side parser that handled the original bytes.
FAQ
Can an SVG file cause an XXE attack?
Yes. SVG is XML, so an unsafe server-side parser may process a DTD or external entity before SVG sanitization. Depending on the environment, that can lead to file reads, server-side network requests, resource exhaustion, or information leakage through errors.
Does removing the DOCTYPE with a regex prevent SVG XXE?
No. Reject DTDs and disable external entity resolution in the parser itself. Regex cleanup is fragile and does not provide parser resource limits, network isolation, or protection across every XML syntax and library behavior.
Is DOMPurify enough to stop XXE in an SVG upload?
No. DOMPurify is valuable for sanitizing browser-facing SVG markup after parsing. XXE prevention requires safe server-side XML parser configuration before that stage, followed by SVG sanitization for scripts, event handlers, unsafe URLs, and embedded content.
What should an SVG upload pipeline reject before parsing?
Reject oversized input, unsupported compressed containers, and files containing DTD or entity declarations. Then parse with external capabilities disabled, enforce document limits, sanitize to an SVG allowlist, and render only the cleaned result.
How do I test whether my SVG parser resolves external entities?
Use harmless fixtures in an isolated test environment. Assert that DTD-bearing input is rejected, controlled external URLs receive zero requests, local marker content never appears in output or errors, and expansion-heavy documents stop within strict time and memory limits.
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