XML External Entity (XXE)
Improper Restriction of XML External Entity Reference (XXE)
What it is
CWE-611 exists when an XML parser processes documents with external entity references enabled, allowing an attacker who controls the XML input to read local files, issue HTTP requests from the server (SSRF), enumerate ports on the internal network, or cause denial of service via entity expansion attacks.
Why it matters
XXE persisted long after XML peaked because so much enterprise infrastructure (SAML, SOAP, DOCX, SVG, XMP metadata, configuration files) still uses XML internally. SAML parsers in particular have been a recurring source of XXE in identity-provider integrations: a malicious SAML response can disclose /etc/passwd from the relying party. SVG processors used in image upload pipelines can be XXE vectors too. The vulnerability class predates the CWE Top 25 but is still flagged in OWASP Top 10 (A05:2021 Security Misconfiguration).
Common patterns
- •Python lxml.etree.parse or xml.etree without explicit resolve_entities=False / forbid_dtd=True.
- •Java DocumentBuilderFactory, SAXParserFactory, or XMLInputFactory created without disabling external entities and DTDs.
- •.NET XmlDocument or XmlReader instantiated with default DtdProcessing (Parse rather than Prohibit on older versions).
- •Node libxmljs or xml2js with noent: true.
- •SAML response parsers, SOAP request handlers, DOCX content extractors that pass user-controlled XML to a default parser.
- •SVG sanitizers that fail to strip external entity declarations.
Languages affected
What Deva detects
Deva matches XML parser instantiations across the major language ecosystems and reports any usage that does not explicitly disable external entity resolution, DTDs, and (where applicable) parameter entity expansion. The scanner has specific rules for lxml, xml.etree, defusedxml (recommended), DocumentBuilderFactory, SAXParserFactory, XMLInputFactory, XmlReaderSettings, libxmljs, and xml2js. Findings include the specific feature flag to set and an inline link to the library's secure-defaults guide.
Example
Vulnerable
from lxml import etree
def parse_saml(xml_bytes):
return etree.fromstring(xml_bytes)Fixed
from defusedxml.lxml import fromstring
def parse_saml(xml_bytes):
# defusedxml refuses external entities, DTD processing, and entity expansion.
return fromstring(xml_bytes)Explanation
The vulnerable version uses lxml directly. An attacker submitting <!DOCTYPE foo [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]><root>&xxe;</root> reads the system password file via the server's response or via an HTTP exfiltration callback. The fix uses defusedxml, which is API-compatible with lxml but disables the dangerous features by default. defusedxml is the standard mitigation across the Python ecosystem; for Java, the equivalent is setting the relevant XML features (http://apache.org/xml/features/disallow-doctype-decl=true and external-general-entities=false) on the DocumentBuilderFactory.
Where this fits in OWASP Top 10
Compliance framework mapping
| Framework | Controls |
|---|---|
| OWASP Top 10 (2021) | A05:2021 Security Misconfiguration |
| NIST 800-53 Rev 5 | SI-10 Information Input ValidationCM-6 Configuration Settings |
| PCI-DSS v4.0 | 6.2.4 Software engineering techniques |
| CMMC 2.0 L2 | CM.L2-3.4.6 Least functionality |
Related CWEs
Deva detects CWE-611 alongside 970+ other CWE patterns at write time, with AI-assisted fix generation that maintains compliance.