Application & code
Educational11 minXML External Entity (XXE)
An XML parser processes untrusted documents with external entity resolution enabled, so a crafted DOCTYPE declaration makes the parser fetch local files or network resources — leaking files, forging server-side requests, or exhausting resources.
Classification
- Domain
- Application & code
- ROOTVIEL support
- Educational — Recognized concept, documented for learning — not detected by ROOTVIEL.
- Analysis family
- code-src
- CWE
- CWE-611
- OWASP
- A05:2021-Security Misconfiguration
Definition
XML External Entity injection (XXE) is the abuse of an XML parser that is configured to resolve external entities while parsing untrusted input. XML’s Document Type Definition (DTD) lets a document declare entities — named placeholders — and an external entity points at a URI the parser will fetch and substitute. When the parser honours those declarations on attacker-controlled XML, the document can make the server read local files, open network connections, or expand entities into enormous payloads.
The defect is parser configuration, not a flaw in XML itself: most parsers historically resolved external entities by default, so merely parsing an untrusted document was dangerous. The fix is almost entirely a matter of disabling DTD processing and external entity resolution before the document is parsed. XXE is classed under Security Misconfiguration because it is overwhelmingly a default-configuration problem.
Context
XXE appears wherever a server accepts XML from a client or third party and parses it with a general-purpose XML library: SOAP and legacy XML APIs, SAML assertions, document formats that are really zipped XML (office documents, SVG, some image metadata), configuration and sitemap uploads, and any file-import feature that accepts XML. It also appears in XML-adjacent formats parsed by XML engines.
- ▸Endpoints that accept XML bodies (SOAP, XML-RPC, legacy REST-over-XML).
- ▸SAML/SSO assertion processing and other signed-XML flows.
- ▸Uploads of XML-based formats: SVG, office documents (zipped XML), RSS/Atom, sitemaps, SpreadsheetML.
- ▸Server-side XML transformation or validation pipelines (XSLT, schema validation) on untrusted input.
- ▸Any parser left on default settings where external entity/DTD processing is enabled.
Technical fundamentals
An XML document may begin with a DOCTYPE that defines entities. A general entity like `<!ENTITY x "value">` substitutes text; an external general entity like `<!ENTITY x SYSTEM "file:///path">` tells the parser to fetch that URI and substitute its contents. External entities can use file://, http://, and other schemes depending on the library, which is what turns a parsing operation into a file read or a network request. Parameter entities and nested definitions enable blind exfiltration and amplification even when the document’s output is never reflected.
The clean model is a dangerous capability enabled by default: the sink is the XML parse call, and the dangerous behaviour is external resolution. Unlike injection flaws, you do not need to sanitise the input — you remove the capability. Set the parser to forbid DTDs entirely (or at least disable external general and parameter entities and external DTD loading) before parsing untrusted XML. Because safe settings differ per library, the control is to configure every XML parser explicitly rather than relying on defaults.
- External entity
- A DTD-declared entity whose value is fetched from a URI (file://, http://…) and substituted during parsing.
- Parameter entity
- An entity used within the DTD itself; central to blind/out-of-band XXE and to amplification attacks.
- Billion-laughs
- An entity-expansion denial of service where nested entities expand exponentially and exhaust memory/CPU.
- Out-of-band (OOB) XXE
- Exfiltration where the parser sends data to an attacker-controlled server because the file content is not reflected back directly.
Root cause
The root cause is parsing untrusted XML with a parser whose default configuration resolves external entities and processes DTDs. The developer calls the standard parse method and assumes it only reads data, not realising the parser will dereference URIs the document names. The fix is configuration hardening at the parser: disable DTDs and external entity resolution before parsing anything that came from outside.
A reinforcing cause is the proliferation of XML parsers across a codebase (direct parsing, schema validation, XSLT, document libraries), each with its own hardening switches and defaults. Missing one parser is enough. The durable answer is a single hardened factory/wrapper used everywhere, so no code path parses untrusted XML with unsafe settings.
How the attack works, step by step
- 1An endpoint accepts an XML document and parses it with external entity resolution enabled.
- 2The attacker submits XML with a DOCTYPE that declares an external entity pointing at a sensitive URI, e.g. file:///etc/hostname or an internal http:// address.
- 3The parser fetches the URI and substitutes the content where the entity is referenced in the document.
- 4If the document’s parsed content is reflected back, the file contents or internal response are returned to the attacker (in-band). If not, parameter entities route the data to an attacker-controlled server (out-of-band).
- 5Because external resolution was enabled, the parse operation itself performed the file read or network request on the server’s behalf.
Two variants extend the impact: using http:// or other schemes turns XXE into server-side request forgery against internal services and cloud metadata; and exponential entity expansion (billion-laughs) turns a tiny document into a memory-exhaustion denial of service.
Vulnerable example
A synthetic, illustrative handler that parses an uploaded XML document with a default-configured parser, plus the shape of a malicious document:
synthetic (Java-style pseudocode) — do not use; illustrates the flaw// UNSAFE: default parser resolves external entities and DTDs. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); // no hardening applied Document doc = db.parse(request.getInputStream()); // sink: external entities resolved String value = doc.getElementsByTagName("name").item(0).getTextContent(); /* Attacker uploads: <?xml version="1.0"?> <!DOCTYPE r [ <!ENTITY secret SYSTEM "file:///etc/hostname"> ]> <r><name>&secret;</name></r> The parser fetches the file and substitutes it into <name>, which is then reflected back to the attacker. */
Corrected example
The fix is to disable DTDs and external entity resolution on the parser before parsing untrusted XML. Centralise the hardened configuration so every XML parse in the codebase inherits it.
synthetic (Java-style pseudocode) — hardened parser factory// SAFER: forbid DTDs entirely; disable external entities and external DTD loads. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // The single most effective switch: reject any document with a DOCTYPE. dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // Belt-and-braces for parsers where disallow-doctype is unavailable. dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); dbf.setAttribute("http://javax.xml.XMLConstants/property/accessExternalDTD", ""); dbf.setXIncludeAware(false); dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(request.getInputStream()); // DTDs rejected: XXE removed
Limit of the fix: the exact switches differ per library and language — the names above are illustrative of the Java/SAX family; other stacks (lxml, .NET XmlReader, Expat-based parsers) have their own flags, and some are safe-by-default in recent versions but not in older ones. Disabling DTDs outright is the strongest single control; where a format legitimately needs DTDs, disable only external entities and cap entity expansion to stop billion-laughs. Every parser in the codebase must be hardened — one default-configured parser reopens the hole.
Impact
- ▸Confidentiality: read local files (configuration, secrets, keys) via file:// entities, in-band or out-of-band.
- ▸Server-side request forgery: use http:// entities to reach internal services and cloud metadata endpoints.
- ▸Denial of service: entity-expansion bombs (billion-laughs) exhaust memory and CPU.
- ▸Pivoting: combine file reads and internal requests to map and attack the internal network.
Detection
Detection has two complementary angles. Statically, inventory every XML parser instantiation and check whether DTD/external-entity processing is disabled before untrusted input is parsed; an unhardened parser on a request-reachable path is the structural signal. Dynamically, submit documents declaring a benign external entity pointing at an attacker-controlled server (an out-of-band callback) and observe whether the server dereferences it; an observed callback is strong evidence. A configuration review of the shared parser factory is often the quickest reliable check.
Where ROOTVIEL fits
This entry is reference material. ROOTVIEL’s verified, execute-and-prove engine is focused on the AI/agentic and Web3 domains, where it confirms a finding by running the attack in a sandbox against a deterministic check. XXE is an application/code (and configuration) weakness that ROOTVIEL does not currently settle with a verified engine, so a finding here is educational unless it is independently demonstrated against the target’s parsers.
Support: educational. Unhardened parser configuration is detectable by inspection, but ROOTVIEL does not promote a verified XXE finding. Treat an unhardened parser as a hypothesis to confirm with an out-of-band probe, not as a proven vulnerability.
Mitigation
Harden every XML parser; prefer removing DTD processing entirely for untrusted input.
- ▸Preventive: disable DOCTYPE/DTD processing on every parser that handles untrusted XML; where DTDs are unavoidable, disable external general and parameter entities and external DTD loading.
- ▸Preventive: centralise a single hardened parser factory/wrapper and use it everywhere so no path parses with defaults.
- ▸Preventive: cap entity expansion and document size to defeat billion-laughs.
- ▸Preventive: where possible, accept a simpler data format (JSON) instead of XML, removing the entire DTD surface.
- ▸Detective: inventory XML parser usage in static analysis and review the shared configuration.
Verifying the mitigation
Verify by confirming every XML parse path uses the hardened configuration (DTDs rejected or external entities disabled, expansion capped). Then attempt exploitation: submit documents with file:// and http:// external entities and an out-of-band callback, plus an expansion bomb, and confirm no file is read, no internal request is made, and no resource exhaustion occurs. Report as "these attempts failed against the tested parsers", not as a blanket guarantee, since a new or overlooked parser can reintroduce the issue.
A clean result covers only the parsers you tested and their current library versions. New code paths, third-party libraries that parse XML internally, and version downgrades can reopen XXE, so keep the shared hardened factory authoritative and re-check after dependency changes.
Common mistakes
- ▸Hardening the obvious parser but leaving a second one (schema validation, XSLT, a document library) on defaults.
- ▸Disabling external general entities but forgetting external parameter entities, which enable blind/out-of-band XXE.
- ▸Assuming a library is safe-by-default without confirming the version and configuration actually in use.
- ▸Fixing external-entity reads but ignoring entity-expansion DoS (billion-laughs).
- ▸Treating absence of reflected output as safety, missing out-of-band exfiltration channels.
References
- [1]MITRE CWE-611 (Improper Restriction of XML External Entity Reference)
- [2]OWASP Top 10 — A05:2021 Security Misconfiguration
- [3]OWASP Cheat Sheet — XML External Entity Prevention
- [4]PortSwigger Web Security Academy — XXE injection
References point to public, well-known technical sources for further study.
Related articles
