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

XML Entity Expansion (Billion Laughs / XXE)

security CWE-611 OWASP A5:2021 CVSS 9.1 PHP 5.0+ Intermediate

Also Known As

billion laughs attack XML bomb exponential entity expansion

TL;DR

Denial-of-service via exponentially nested XML entities (Billion Laughs) or SSRF/file-read via external entity references (XXE).

Explanation

Two related XML attacks: the Billion Laughs DoS defines nested entities that expand exponentially (lol1 = 10×lol0, lol2 = 10×lol1 ... lol9 = billions of characters), exhausting server memory parsing a tiny document. XXE (XML External Entity) uses <!ENTITY ext SYSTEM 'file:///etc/passwd'> to read local files or <!ENTITY ext SYSTEM 'http://internal/'> to trigger SSRF. PHP's libxml is vulnerable by default. Mitigations: call libxml_disable_entity_loader(true) (PHP < 8.0) or use LIBXML_NONET | LIBXML_NOENT flags with simplexml_load_string() / DOMDocument::loadXML(). In PHP 8.0+ external entity loading is disabled by default. Never parse untrusted XML with a SAX/DOM parser that hasn't had entity expansion disabled.

Common Misconception

XML entity expansion is only a theoretical DoS risk. A crafted document with nested entity references can expand to gigabytes in memory from kilobytes of input, crashing a server in milliseconds. Always disable entity expansion when parsing untrusted XML.

Why It Matters

The billion laughs attack uses nested entity references to expand a small XML document to gigabytes, exhausting memory and crashing the parser — one request, full DoS.

Common Mistakes

  • Parsing user-supplied XML without setting LIBXML_NOENT to disable entity expansion.
  • Using SimpleXML or DOMDocument on untrusted input without calling libxml_disable_entity_loader(true) first.
  • Not setting resource limits (memory, CPU time) for XML parsing operations.
  • Assuming entity attacks only apply to XXE — expansion attacks do not require external entity loading.

Avoid When

  • Never parse user-supplied XML with unlimited entity expansion enabled — a single crafted document can exhaust server memory.
  • Do not use DOMDocument or SimpleXML on untrusted input without configuring safe parse options first.

When To Use

  • Disable entity expansion when parsing untrusted XML using LIBXML_NOENT awareness and libxml_disable_entity_loader().
  • Set a maximum entity expansion depth/count limit when processing XML from external sources.

Code Examples

✗ Vulnerable
$xml = simplexml_load_string($untrusted); // XXE possible pre-PHP 8
✓ Fixed
libxml_disable_entity_loader(true); // PHP < 8.0
$xml = simplexml_load_string($untrusted, 'SimpleXMLElement', LIBXML_NOENT | LIBXML_NONET);

Tags


Added 15 Mar 2026
Edited 31 Mar 2026
Views 18
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 2 Unknown AI 2 ChatGPT 2 Ahrefs 1 Google 1
crawler 13 crawler_json 2
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Low
⚡ Quick Fix
Set LIBXML_NONET when parsing XML and configure libxml_disable_entity_loader(true) for PHP < 8.0 — Billion Laughs attack uses nested entity expansion to exhaust memory with a tiny XML file
📦 Applies To
PHP 5.0+ web api cli
🔗 Prerequisites
🔍 Detection Hints
XML parsing without entity expansion limits; LIBXML_NOENT not disabled; simplexml_load_string without entity restrictions
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-776 CWE-400

✓ schema.org compliant