XXE - XML External Entity Processing
An XML parser is configured to resolve external entities, so an attacker's document can name a SYSTEM entity and make the parser read a local file or send a request from the server. Findings are reported under API8:2023 Security Misconfiguration.
What Vulkro detects
Configuration shapes read from the parser construction; the parser is never run.
| Rule | Language | Fires on | Severity |
|---|---|---|---|
| (lxml check) | Python | lxml.etree.XMLParser with resolve_entities=True, no_network=False or load_dtd=True | High, High confidence |
XXE-PY-001 | Python | xml.sax with the external general or parameter entity feature enabled; suppressed when the file imports defusedxml | High |
XXE-JS-001 | JavaScript | libxmljs / libxmljs2 parse with noent: true | High |
XXE-JS-002 | JavaScript | xmldom / @xmldom/xmldom DOMParser().parseFromString(...); heuristic (runtime version not visible) | Medium |
XXE-GO-001 | Go | a parse through a third-party libxml2 binding (stdlib encoding/xml is safe); heuristic | Medium |
JAVA-XXE-001 | Java | a JAXP factory, dom4j SAXReader or JDOM SAXBuilder parses a request-derived value in a file with no hardening | High, Medium confidence |
JAVA-XXE-002 | Java | a method that builds a parser and parses one of its own parameters with no unconditional hardening (no taint needed) | Medium, Medium confidence |
JAVA-XXE-003 | Java | a call site passing a request-derived value to a helper flagged by JAVA-XXE-002 | High, Medium confidence |
Java: unconditional hardening anywhere in the file silences JAVA-XXE-001; hardening inside a branch (if (x) { ... }) does not count (Allman-style braces are a known gap). JAVA-XXE-003 needs a matching receiver type, method name and tainted argument; unresolved receivers are skipped.
A finding means the parser resolves external entities (in Java: no visible hardening), not that an exploit exists. Billion-laughs denial of service is a separate, lower-severity signal.
Non-compliant code
# lxml parser with every protection off
from lxml import etree
parser = etree.XMLParser(resolve_entities=True, load_dtd=True, no_network=False)
doc = etree.fromstring(request_body, parser) # SYSTEM entities resolve
Compliant code
from defusedxml.lxml import fromstring
doc = fromstring(request_body)
How to fix
- Python:
defusedxml, or lxml withresolve_entities=False, load_dtd=False, no_network=True. - Java: set
disallow-doctype-declandFEATURE_SECURE_PROCESSINGon the factory. - libxml2: no
NOENT, network off. Go: stdlibencoding/xml.
References
See also: Confidence model.
This page is generated by vulkro rules export <out-dir> from Vulkro's built-in detector catalogue. Edits made by hand are overwritten on the next regeneration.