← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

XML External Entity (XXE)

security CWE-611 OWASP A5:2021 CVSS 8.2 PHP 5.0+ Advanced
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep and psalm as tools, both specialist SAST tools that catch the pattern of simplexml_load_string or DOMDocument->loadXML without proper entity disabling. This is not caught by the compiler or a default linter, but is reachable by deliberate SAST integration.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is 'Set libxml_disable_entity_loader(true) and LIBXML_NOENT off; use JSON instead of XML where possible'. While the core fix is a one-liner, the common_mistakes note that every XML parsing site across the codebase needs the same treatment — REST endpoints, SimpleXML calls, DOMDocument calls — making it a small but recurring pattern-replacement fix rather than a single-line patch.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to scope is web and CLI PHP contexts, but the burden is limited to XML parsing sites. It imposes a configuration tax wherever XML is parsed, but it does not shape the broader architecture. Teams that adopt a centralised XML parsing wrapper reduce this further, so it stays at b3.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field explicitly states that disabling DOCTYPE declarations is believed to fully prevent XXE but does not — parameter entities can bypass this, and many XML libraries enable external entities by default. A common_mistake compounds this: LIBXML_NOENT is widely misread as 'no entities' when it actually substitutes them. These two counter-intuitive behaviours together mean a competent developer following apparent best practice can still be vulnerable, warranting t7.

About DEBT scoring →

Also Known As

XML External Entity XXE injection XML external entity attack

TL;DR

A vulnerable XML parser processes external entity references, letting attackers read local files or trigger SSRF.

Explanation

XXE exploits XML parsers that resolve external entity declarations — specially crafted XML that references system files (<!ENTITY xxe SYSTEM "file:///etc/passwd">) or internal network resources. Consequences include arbitrary file read, SSRF, and in some configurations denial of service via billion-laughs recursive entity expansion. In PHP, disable external entity loading: libxml_disable_entity_loader(true) before parsing, or use SimpleXML with LIBXML_NONET.

How It's Exploited

<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<data>&xxe;</data>
# Server returns /etc/passwd contents in the response

Common Misconception

Disabling DOCTYPE declarations fully prevents XXE. Some XXE vectors use parameter entities that do not require DOCTYPE. Additionally, many XML libraries enable external entities by default — the safe approach is explicitly disabling entity processing in every parser configuration.

Why It Matters

XML External Entities allow the XML parser to fetch and embed local files or URLs — exposing /etc/passwd, cloud metadata endpoints, or triggering SSRF via a single XML document.

Common Mistakes

  • Not disabling external entity loading before parsing XML: libxml_disable_entity_loader(true) is required.
  • Using SimpleXML or DOMDocument::loadXML() on untrusted input without suppressing entity processing.
  • Accepting XML in API endpoints — REST endpoints that accept application/xml need the same protections.
  • Thinking that LIBXML_NOENT alone is sufficient — it actually substitutes entities rather than disabling them.

Avoid When

  • Never parse user-supplied XML with external entity loading enabled — even internal XML from APIs can be compromised.
  • Do not use SimpleXML on untrusted input without disabling external entities first.

When To Use

  • Disable external entity loading whenever parsing XML from any untrusted source.
  • Use libxml_disable_entity_loader(true) (PHP < 8.0) or LIBXML_NOENT flag awareness on all XML parsing.

Code Examples

✗ Vulnerable
// Loads external entities — file disclosure or SSRF
$xml = simplexml_load_string($userInput);
✓ Fixed
// Disable external entity loading before parsing
libxml_disable_entity_loader(true); // PHP < 8.0
// PHP 8.0+ disables it by default

$xml = new DOMDocument();
$xml->loadXML($userInput, LIBXML_NONET | LIBXML_NOENT);

// Or use SimpleXML with the same flags
$xml = simplexml_load_string($userInput, 'SimpleXMLElement', LIBXML_NONET | LIBXML_NOENT);

Added 15 Mar 2026
Edited 31 Mar 2026
Views 24
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 1 ping T 0 pings W 1 ping T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 3 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 10 Perplexity 3 Google 3 Unknown AI 2 Ahrefs 2 Bing 1
crawler 17 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Low
⚡ Quick Fix
Set libxml_disable_entity_loader(true) and LIBXML_NOENT off; use JSON instead of XML where possible
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
simplexml_load_string( or DOMDocument->loadXML( without LIBXML_NOENT disabled
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-611 CWE-827

✓ schema.org compliant