GitHub Advisoryadvisory · PyPI
GHSA-97qj-x29f-37w7 NLTK: Entity-expansion DoS (billion laughs) via remaining raw ElementTree parses
HIGH
Official page ↗
- Aliases
- CVE-2026-78681
- Ecosystem
- PyPI
- Packages
- nltk
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- Weaknesses
- CWE-776
- Reviewed
- 2026-09-08
Affected packages
• PyPI nltk: < 3.10.3 → fixed in 3.10.3
Description
Several XML parsing sites in NLTK still used `xml.etree.ElementTree` directly, which honours `` declarations in a document's internal DTD subset. A crafted document a few hundred bytes long can expand to megabytes in memory (each nesting level multiplies by ten), a denial-of-service.
Affected call sites (' for i in range(1, levels+1))
return f'{d}]>&e{levels};'
ET.fromstring(bomb(5)) # -> element whose .text is 1,000,000 chars
```
2. The patched entry point rejects it
```
>>> from nltk.internals import ElementWrapper
>>> ElementWrapper(bomb(5))
EntitiesForbidden: EntitiesForbidden(name='e0', ...)
```
3. Why a text-based screen is not enough
An entity declaration can hide behind a decoy `` in a prolog comment. Raw ElementTree still processes the real declaration and expands; a guard that walks the DOCTYPE text is fooled. The shipped guard re-parses with expat, so it is not:
```python
evil = ' -->]>&a;'
```
```
raw ElementTree -> EXPANDS ('PPPPPPPPPPPP...', 40 chars)
nltk.xmlsec -> REJECTED (EntitiesForbidden)
```
An earlier draft of the fallback that walked the text was bypassed by this and 4 similar payloads (decoy DOCTYPE in a PI, stray `]` inside a PI in the internal subset). All five are now regression tests.
4. Both back ends block it
`nltk.xmlsec` prefers `defusedxml` and falls back to a stdlib `xml.parsers.expat` pre-scan. Same payloads, defusedxml hidden to force the fallback:
```
stdlib fallback | billion-laughs -> REJECTED (EntitiesForbidden)
stdlib fallback | comment-decoy differential -> REJECTED (EntitiesForbidden)
```
Environment: python 3.13.7, libexpat 2.7.1. Confirmed identical amplification on python 3.10 (NLTK's floor).
Related
Alias · CVE (1)
- CVE-2026-78681 NLTK versions before 3.10.3 use xml.etree.ElementTree to parse XML in multiple modules, which honors entity declarations in document DTDs. vulnerability
Weakness · CWE (1)
- CWE-776 Improper Restriction of Recursive Entity References in DTDs weakness
References
- https://github.com/nltk/nltk/security/advisories/GHSA-97qj-x29f-37w7 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-78681 advisory
- https://github.com/nltk/nltk/commit/e91789c9a043296ad04912ce171c22776d45963b web
- https://github.com/nltk/nltk package
- https://github.com/nltk/nltk/releases/tag/v3.10.3 web
- https://github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-3748.yaml web
- https://www.vulncheck.com/advisories/nltk-before-entity-expansion-dos-via-elementtree web