An XML parser that honours document type definitions will fetch whatever an untrusted document tells it to, from local files to internal web services. That behaviour, XML External Entity (XXE) processing, is catalogued as CWE-611 and sits inside OWASP Top 10 2021 category A05 Security Misconfiguration, because in most cases the fix is a parser setting rather than a code rewrite. XXE keeps reappearing in the CISA Known Exploited Vulnerabilities (KEV) catalogue, in products from Adobe Commerce to GeoServer. This guide explains how the weakness works at a conceptual level, where XML hides in modern applications, how to detect it, and the exact secure parser settings for Java, .NET, PHP, Python, C and C++. It is written for application security engineers, developers and reviewers, and deliberately contains no attack strings.
Key takeaways
- XXE is a configuration flaw. The parser, not the business logic, resolves external entities; disabling DTD processing removes the whole class in most stacks.
- XML is in more places than your API. SAML assertions, SOAP services, SVG images, Office documents, RSS feeds and document converters all parse XML, often through a library you did not configure.
- Defaults differ by language and version. .NET 4.5.2 and later, libxml2 2.9 and later, and lxml 5.x are safe by default for external entities; Java JAXP factories are not.
- Impact goes beyond file reads. CWE-611 lists confidentiality loss, server-side request forgery style outbound requests and denial of service; NVD rates the Adobe Commerce XXE (CVE-2024-34102) 9.8 with possible code execution.
- Prove it with tests, not assumptions. A unit test per parser that feeds a document with a DTD and expects rejection catches regressions that code review misses.
How the attack works
XML 1.0 lets a document carry a document type definition (DTD). A DTD can declare entities: named placeholders the parser substitutes while it builds the document. An external entity points to a URI, and a permissive parser dereferences that URI and inlines the result. CWE-611 describes the weakness as a parser processing entities whose URIs resolve to documents outside the intended sphere of control. MITRE classes it as a child of CWE-610 (externally controlled reference to a resource in another sphere) and notes its close relationship to CWE-918 SSRF, because both make the server issue requests to destinations the attacker chooses.
- In-band XXE: the resolved content is reflected in the application's response, for example in an error message or an echoed field.
- Blind XXE: nothing is reflected. The OWASP Web Security Testing Guide (WSTG-INPV-07) notes that blind variants are confirmed through out-of-band interaction or error messages, so an application that "returns nothing" is not proven safe.
- Parameter entities: entities used inside the DTD itself. Several parsers control these with a separate switch from general entities, which is why disabling only one setting leaves a gap.
- Entity expansion denial of service: internal entities that reference each other (the "billion laughs" pattern, CAPEC-221 Data Serialization External Entities Blowup) or one large entity repeated many times (quadratic blowup) exhaust memory and CPU without any external resource at all.
- XInclude: a separate W3C mechanism that also pulls in external content. OWASP advises keeping it disabled even when entities are off.
- Second-order XXE: the XML is stored first (an uploaded file, a queued message, an imported feed) and parsed later by a back-end job, often with weaker settings and broader network access than the front end.
Where it shows up
The WSTG warns that a hardened primary API does not make other XML paths safe. Inventory every place your estate parses XML, including formats that do not look like XML to users.
| Entry point | Why it parses XML | What to check |
|---|---|---|
| SOAP and XML-RPC services | Request bodies are XML by definition | Framework parser settings; legacy endpoints left enabled |
| REST APIs with content negotiation | Some frameworks accept application/xml alongside JSON | Whether XML binding is enabled when only JSON is needed |
| SAML single sign-on | Assertions and metadata are signed XML | SAML library version and its parser configuration. See the SAML Security Guide. |
| File uploads and conversion | SVG, DOCX, XLSX, PPTX, ODF and EPUB contain XML; CWE-611 lists CVE-2012-5656 (SVG conversion) and CVE-2012-0037 (office RDF) | Image and document processing libraries, content extraction tools. See the File Upload Security Guide. |
| Feeds, sitemaps and imports | RSS, Atom, partner data exchange, configuration import | Scheduled jobs that parse fetched content |
| XSLT and schema validation | Stylesheets and XSD imports can reference external resources | ACCESS_EXTERNAL_STYLESHEET and ACCESS_EXTERNAL_SCHEMA in Java |
| Geospatial, ERP and middleware products | OGC services, SAP and integration buses exchange XML | Vendor patches tracked in KEV, for example GeoServer CVE-2025-58360 (WMS GetMap) and SAP NetWeaver CVE-2016-9563 |
Commercial software is a large share of the exposure. The KEV catalogue (local copy, October 2026) lists CWE-611 flaws in Adobe Commerce and Magento Open Source, SysAid On-Prem (CVE-2025-2775 and CVE-2025-2776), North Grid Proself, Zimbra Collaboration Suite, Citrix StoreFront Server, SAP NetWeaver and GeoServer. For these, the control is patch management rather than code change. See the Vulnerability Scanning Guide.
Impact
| Impact (CWE-611 consequence) | What it means in practice | What limits the damage |
|---|---|---|
| Confidentiality: local file disclosure | Configuration files, application secrets, keys and source readable by the parsing process | Secrets in a vault rather than files; parser process running as a low-privilege account |
| Integrity: forced outbound requests | Requests to internal services and cloud metadata endpoints, bypassing perimeter firewalls and abusing trust relationships | Egress filtering, IMDSv2-style token-protected metadata, network segmentation |
| Availability: resource exhaustion | Entity expansion, very large files or endless device streams consume memory and CPU | Entity limits, input size limits, decompressed size limits, timeouts |
| Escalation to code execution | Product-specific chains; NVD describes CVE-2024-34102 in Adobe Commerce as XXE that "could result in arbitrary code execution" | Patching, runtime isolation, WAF virtual patching while patching |
The outbound request path is the reason XXE belongs in the same review as SSRF. See the SSRF Prevention Guide.
Where identity fits
The most valuable files on an application server are usually machine credentials: database connection strings, API keys, service account key files and cloud role credentials reachable through instance metadata. An XXE file read is therefore frequently an NHI credential theft. Keep secrets out of readable files and short-lived where possible, so that a disclosed value expires before it can be reused. See the Secrets Management Guide.
Detection
- Static analysis: CWE-611 rates automated static analysis as highly effective. Configure SAST rules that flag parser factories created without the secure features below, and run them on every pull request.
- Configuration review: WSTG-INPV-07 recommends white-box review of parser settings across the codebase and its dependencies. Search for
DocumentBuilderFactory,SAXParserFactory,XMLInputFactory,TransformerFactory,XmlDocument,LIBXML_NOENTandresolve_entities. - Dynamic testing: include XXE checks (in-band and out-of-band) for every XML-accepting endpoint and every upload type that carries XML. See the Web Application Security Testing Guide.
- Dependency and product scanning: track CWE-611 advisories for XML libraries and for commercial products, prioritising KEV entries.
- Runtime signals: alert on application servers making unexpected outbound DNS or HTTP requests, on access to metadata endpoints from application processes, and on parser exceptions mentioning DOCTYPE or DTD. A WAF can log request bodies containing DOCTYPE declarations on endpoints that never legitimately receive them. See the Web Application Firewall Guide.
Metrics
- Parser coverage: percentage of XML parsing call sites with a verified secure configuration and a regression test.
- Open CWE-611 findings: count and age of open SAST, DAST and penetration test findings.
- KEV patch time: days from KEV listing to patch for CWE-611 product flaws, against the KEV due date.
- XML surface: number of endpoints accepting
application/xmlor XML-based uploads, trending down where XML is unnecessary. - Egress exceptions: number of application workloads with unrestricted outbound internet access.
Prevention and hardening
OWASP's guiding rule: disable DTDs where possible, keep XInclude disabled, and treat any unsupported security setting as a failure rather than continuing with partial hardening.
Secure parser settings by platform
| Platform | Secure setting | Notes |
|---|---|---|
| Java DOM and SAX (JAXP) | http://apache.org/xml/features/disallow-doctype-decl = true, plus XMLConstants.FEATURE_SECURE_PROCESSING = true | setExpandEntityReferences(false) is not a substitute. If DTDs are required, set external-general-entities, external-parameter-entities and load-external-dtd to false |
| Java StAX | XMLInputFactory.SUPPORT_DTD = false and IS_SUPPORTING_EXTERNAL_ENTITIES = false | StAX does not support secure processing; add an XMLResolver that rejects external references |
| Java XSLT and schema | Secure processing on, then ACCESS_EXTERNAL_DTD, ACCESS_EXTERNAL_STYLESHEET and ACCESS_EXTERNAL_SCHEMA set to an empty string | Validators do not inherit the factory's resolver; never pass untrusted input to java.beans.XMLDecoder |
| .NET | XmlReaderSettings.DtdProcessing = Prohibit (the default for XmlReader); XmlResolver null | 4.5.2 and later default to a null resolver; for ASP.NET set <httpRuntime targetFramework> to 4.5.2 or later, as <compilation targetFramework> is not enough |
| PHP (libxml) | Do not pass LIBXML_NOENT, LIBXML_DTDLOAD or LIBXML_DTDVALID for untrusted XML | libxml 2.9.0 and later disable entity substitution by default; use an external entity loader callback that returns null |
| Python | defusedxml in place of standard library parsers, with forbid_dtd=True; lxml with resolve_entities=False | defusedxml defaults forbid_entities and forbid_external to true; lxml 5.x disables XXE by default; keep Expat at 2.7.2 or later for entity expansion protection |
| C (libxml2) | Never set XML_PARSE_NOENT or XML_PARSE_DTDLOAD | Check xmlReadMemory, xmlCtxtReadFile and xmlCtxtUseOptions call sites |
| C++ (Xerces-C++) | setDisableDefaultEntityResolution(true); for SAX2 set fgXercesDisableDefaultEntityResolution | Custom resolvers must also reject unapproved resources |
| iOS | NSXMLNodeLoadExternalEntitiesNever when creating NSXMLDocument | Older iOS libxml2 builds predate 2.9 protections |
Decision guidance
- Do you need XML at all? If an endpoint can accept JSON only, remove XML binding. This is the cheapest and most complete fix.
- Disallow DTDs vs restrict them: disallowing DOCTYPE declarations is preferred because it also stops entity expansion denial of service. Choose the restrictive per-feature settings only when a legitimate format needs inline DTDs, and add entity expansion limits.
- Central wrapper vs per-call configuration: large codebases should expose one approved parser factory and ban direct factory construction through lint rules. Small teams can rely on the platform default where it is safe, plus a test.
- Library you do not control: check whether wrappers such as dom4j, JDOM or Commons Digester replace the reader's resolver, as OWASP warns. If a product is affected, patch and apply a WAF rule as a temporary measure.
Defence in depth
- Least privilege: run XML processing in a process or container that cannot read secrets and has no unnecessary file system access.
- Egress control: deny outbound connections from parsing workloads by default, and require tokens for cloud metadata services.
- Size limits: bound request size and decompressed size independently; Python's documentation names decompression bombs as a risk for any library parsing compressed streams.
- Patching: keep XML libraries current, since parser defaults and expansion limits have improved over time.
Rollout plan
- Inventory: list every XML parsing call site, framework and product, using code search, SAST and the upload type list above.
- Write failing tests first: for each parser, a unit test feeding a harmless document containing a DOCTYPE declaration and expecting rejection or no external access.
- Apply the secure settings through a shared factory, starting with internet-facing and upload paths.
- Pilot in staging with real partner and SAML traffic replayed, watching for legitimate documents that carry DTDs.
- Roll out by service behind a configuration flag; if a partner format breaks, roll back that service only and switch it to the restrictive per-feature settings rather than re-enabling everything.
- Lock in: enable SAST rules as blocking, add the tests to CI and record the standard in your secure coding baseline. See the Secure Coding Guide.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| CWE | CWE-611; related CWE-918 | Weakness definition |
| OWASP Top 10 2021 | A05 Security Misconfiguration | CWE-611 is a notable CWE in this category |
| OWASP ASVS 5.0 | V1.5.1 | XML parsers use a restrictive configuration with external entity resolution disabled |
| OWASP WSTG | WSTG-INPV-07 | Testing for XML injection, including XXE |
| MITRE CAPEC | CAPEC-221, CAPEC-250 | External entities blowup; XML injection |
| MITRE ATT&CK | T1190 Exploit Public-Facing Application | How XXE in internet-facing products is used for initial access |
| NIST SP 800-53 Rev. 5 | SI-10, CM-6, CM-7, SA-11, SC-7, SI-2, RA-5 | Input validation, secure configuration, least functionality, developer testing, boundary protection, patching, scanning |
| NIST CSF 2.0 | PR.PS-01, PR.PS-06, ID.RA-01, DE.CM-09 | Configuration management, secure development, vulnerability identification, runtime monitoring |
Common failure patterns
- Fixing one factory and missing the rest: the DOM parser is hardened, but the XSLT, schema validator or StAX reader in the same service is not. WSTG-INPV-07 calls this out explicitly.
- Trusting an expand-entities flag: in Java,
setExpandEntityReferences(false)changes tree representation only and does not block external resources, according to OWASP. - Forgetting file formats: the JSON API is safe, but an SVG thumbnailer or DOCX text extractor parses uploaded XML with library defaults.
- Back-end jobs with more reach: second-order parsing in a batch worker that has wide egress and mounted credentials.
- Framework version mismatch: an ASP.NET application compiled for a modern framework but with
httpRuntime targetFrameworkbelow 4.5.2 keeps the older, unsafe behaviour. - Treating product XXE as low priority: KEV has listed multiple CWE-611 flaws with federal due dates; a medium internal rating does not reflect active exploitation.
Practitioner checklist
- Inventory every XML parser, XML-based upload type, SAML library and XML-consuming product.
- Remove XML support from endpoints that only need JSON.
- Disallow DOCTYPE declarations by default; where DTDs are required, disable external general entities, parameter entities, external DTD loading and XInclude separately.
- Provide one approved parser factory per language and ban direct construction through lint or SAST rules.
- Add a regression test per parser that expects a document with a DTD to be rejected.
- Set entity expansion and decompressed size limits, and keep libxml2, Expat and other XML libraries patched.
- Run parsing workloads with least privilege, default-deny egress and token-protected metadata access.
- Track CWE-611 KEV entries and patch affected products by the KEV due date.
- Monitor application servers for unexpected outbound DNS and HTTP and for DTD-related parser exceptions.
Standards and references
- OWASP: XML External Entity Prevention Cheat Sheet
- MITRE: CWE-611 Improper Restriction of XML External Entity Reference
- OWASP: Web Security Testing Guide, Testing for XML Injection
- OWASP: Application Security Verification Standard 5.0
- Microsoft Learn: XmlReaderSettings.DtdProcessing Property
- Python Software Foundation: XML Processing Modules, XML security
- NIST NVD: CVE-2024-34102
- CISA: Known Exploited Vulnerabilities Catalog
Related NHI Mgmt Group resources: Web Application Attacks Guide · SSRF Prevention Guide · Insecure Deserialisation Guide · CWE Top 25 Guide