Safeguard
Vulnerability Analysis

What is XML External Entity (XXE) Injection

XXE injection lets attackers abuse XML parsers to read files, trigger SSRF, or crash services. Here's how it works, real CVEs, and how to stop it.

Karan Patel
Security Analyst
6 min read

XML External Entity (XXE) injection is a vulnerability class where an attacker manipulates an application's XML parser into resolving external entity references it should never touch — typically a <!DOCTYPE> declaration with a SYSTEM identifier pointing at a local file, an internal URL, or a crafted protocol handler. When a vulnerable parser processes that entity, it can read arbitrary files (/etc/passwd, cloud metadata endpoints, private keys), make outbound requests on the server's behalf, or hang the process entirely through recursive entity expansion. XXE is tracked as CWE-611 ("Improper Restriction of XML External Entity Reference") and was a standalone OWASP Top 10 category (A4) in 2017 before being folded into "Security Misconfiguration" in the 2021 revision — not because it disappeared, but because the root cause is almost always a parser left in its insecure default state. Any application that ingests XML — SOAP APIs, SAML SSO, DOCX/XLSX/SVG uploads, RSS feeds, config files — is a candidate.

How does an XXE attack actually work?

An XXE attack works by smuggling a custom entity definition into XML input that the parser then dereferences during processing. The classic payload looks like this:

<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<foo>&xxe;</foo>

If the parser has DTD processing and external entity resolution enabled — the default in libxml2 before certain configuration, in older versions of Java's DocumentBuilderFactory, and in many XML libraries shipped before 2015 — it fetches the referenced resource and substitutes its contents into the document the application then returns, logs, or echoes back. Attackers also use parameter entities (<!ENTITY % xxe SYSTEM "...">) for out-of-band exfiltration when the response isn't directly reflected, and blind XXE techniques that trigger a DNS or HTTP callback to a server the attacker controls to confirm exploitation and leak data a few bytes at a time.

What can attackers actually do with an XXE vulnerability?

Attackers can achieve four distinct outcomes: file disclosure, server-side request forgery, denial of service, and in some configurations, remote code execution. File disclosure via file:// lets an attacker pull application source, /etc/passwd, SSH keys, or the AWS instance metadata endpoint (http://169.254.169.254/latest/meta-data/) if the parser will follow http:// in a SYSTEM identifier — this is how XXE frequently pivots into full cloud credential theft. Denial of service is achieved through the "billion laughs" pattern, where nested entity expansion turns a few hundred bytes of XML into gigabytes of memory allocation, crashing the parser. Remote code execution is rarer but documented: PHP's expect:// wrapper combined with XXE, or XXE chained with local file inclusion in a Java deserialization gadget chain, has produced working RCE in real bug bounty reports and CTFs.

Which real-world vulnerabilities show the impact of XXE?

Several tracked CVEs demonstrate that XXE is not a theoretical issue: CVE-2014-3529 in Apache Solr allowed remote attackers to read arbitrary files and cause denial of service through the /select request handler's XML entity processing, and CVE-2018-1000632 in the widely-used dom4j Java library (CVSS 7.5) exposed any downstream application parsing untrusted XML to the same file-disclosure and SSRF risk. Outside of CVE tracking, one of the most cited XXE incidents in the bug bounty community is Reginaldo Silva's 2014 report against Facebook, where an XXE flaw in an OpenID/mobile endpoint was chained toward remote code execution and reportedly earned a $33,500 payout — illustrating how a "just file read" bug can escalate when the parsed XML flows into a privileged code path. Apache CXF's Aegis databinding (CVE-2017-9807) is another example where a widely embedded SOAP framework shipped an XML parser with unsafe defaults for years before the fix landed.

Why do XML parsers process external entities by default?

XML parsers process external entities by default because DTD support predates modern threat models and was built for legitimate document composition, not attacker input. The XML 1.0 specification (finalized in 1998) treats external entities as a normal feature for splitting large documents into includable fragments — useful for publishing workflows, useless and dangerous once XML became a wire format for untrusted API payloads. Libraries like libxml2, Xerces, and the JDK's built-in javax.xml.parsers stack shipped with DTD and external entity resolution enabled out of the box well into the 2010s, so any team that pulled in an XML parser without explicitly hardening it inherited the vulnerability by default. This is precisely why XXE keeps resurfacing in dependency scans years after the "fix" — the fix is a configuration change application developers must make themselves, not a patch the library maintainer can silently ship.

How is XXE different from SSRF and SQL injection?

XXE is different from SSRF and SQL injection because it is a parser-level trust failure specific to XML entity resolution, while SSRF is a broader server-side request issue and SQL injection targets a database query layer. The two do overlap in impact — an XXE payload with an http:// SYSTEM identifier is functionally an SSRF primitive, capable of hitting internal services and cloud metadata endpoints exactly like a traditional SSRF bug — but the injection point and root cause differ: XXE requires an XML parser with DTD processing enabled, whereas SSRF can originate from any code path that fetches a URL supplied by user input (webhooks, image-proxy services, PDF generators). Distinguishing them matters for remediation: fixing XXE means disabling DTDs at the parser level, while fixing SSRF requires network-layer egress controls and allow-listing regardless of file format.

How can you detect and prevent XXE injection?

You prevent XXE by disabling DTD processing and external entity resolution at the parser configuration level, not by sanitizing input. In Java, this means setting DocumentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); in Python's lxml, passing resolve_entities=False to the parser; in PHP, calling libxml_disable_entity_loader(true) (default-on since PHP 8.0, but still required in 7.x deployments); in .NET, avoiding XmlDocument in favor of XmlReader with DtdProcessing.Prohibit. Beyond configuration, OWASP recommends preferring less expressive data formats like JSON where XML isn't a hard requirement, and where XML is mandatory, validating against a known schema (XSD) that rejects unexpected DOCTYPE declarations before parsing. Detection at scale requires both static analysis that flags insecure parser instantiation and dynamic testing (OAST-style blind XXE payloads with out-of-band callback domains) since many XXE sinks don't reflect output directly.

How Safeguard Helps

Safeguard helps security teams move past theoretical CVE lists to what actually matters in their environment. Reachability analysis determines whether the vulnerable XML-parsing code path in a flagged dependency — like a dom4j or Apache CXF version affected by an XXE CVE — is actually invoked by your application's compiled call graph, so triage time goes to exploitable findings instead of dormant ones. Griffin AI reviews the surrounding code to confirm whether input reaching the parser is attacker-controlled and whether safe parser flags are already set, cutting false positives before they reach an engineer's queue. SBOM generation and ingest give teams continuous visibility into every XML-processing library across their services, and for confirmed, reachable XXE findings, Safeguard opens auto-fix pull requests that apply the parser hardening configuration directly, turning a multi-day remediation cycle into a single review-and-merge.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.