CVE-2026-12876 json
NLTK: Uncontrolled resource consumption in RecursiveDescentParser via ambiguous or left-recursive grammars
published 2mo ago modified last mo. also GHSA-ff5c-cp5c-9wjf , PYSEC-2026-3869
- cvss
- —
- not scored
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no EPSS score yet
- public exploits
- 0
- none known
Summary
`nltk.parse.RecursiveDescentParser` (and `SteppingRecursiveDescentParser`) enumerate parses top-down with no bound on the number of recursive steps. A small, crafted context-free grammar makes a short input consume unbounded CPU (and/or exhaust the Python recursion stack), pinning a process indefinitely — a denial of service.
## Proof of concept
Both of the following hang on a 24-token input (killed after 8s; growth is super-linear in input length), on NLTK develop:
```python from nltk import CFG from nltk.parse import RecursiveDescentParser
# (a) left recursion -> unbounded recursion g = CFG.fromstring("S -> S S | 'a'") list(RecursiveDescentParser(g).parse(["a"] * 24)) # hangs
# (b) ambiguous grammar -> exponential number of parses g = CFG.fromstring("S -> 'a' S | 'a' S S | 'a'") list(RecursiveDescentParser(g).parse(["a"] * 24)) # hangs ```
## Impact
An application that runs `RecursiveDescentParser` on a grammar (or an input) drawn from an untrusted source can be driven into an unbounded CPU / stack-exhaustion loop by a tiny payload. No confidentiality or integrity impact; single-process availability only.
## Sibling
The RegexpTokenizer ReDoS reported alongside this (CVE-2026-12875) is a different class (caller-supplied regex) and is addressed under GHSA-w3v8-gmh9-3wv7.
Patch / fix
- pypi nltk 3.10.3
- github.com/nltk/nltk@43aaca1 commit
- github.com/nltk/nltk#3649 pull request
- github.com/nltk/nltk/releases/tag/v3.10.3 release
Is CVE-2026-12876 in your dependencies? Fencer shows which of your repositories are affected as soon as an advisory lands, and opens the fix as a pull request.
Check with FencerAffected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| pypi | nltk | <3.10.3 |
3.10.3 |
Classification
References
-
github.com
/nltk/nltk/pull/3649
web
-
github.com
/nltk/nltk/commit/43aaca1b9024138421c97f970bf13ee19ac8129d
web
-
github.com
/nltk/nltk/security/advisories/GHSA-ff5c-cp5c-9wjf
web
-
github.com
/nltk/nltk
package
-
github.com
/nltk/nltk/releases/tag/v3.10.3
web
-
pypi.org
/project/nltk
package
-
github.com
/advisories/GHSA-ff5c-cp5c-9wjf
advisory
-
nvd.nist.gov
/vuln/detail/CVE-2026-12876
advisory
Sources
- GitHub Advisory GHSA-ff5c-cp5c-9wjf
- OSV PYSEC-2026-3869
Fencer Intel keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.