CVE-2026-81725: NLTK · Pl196xCorpusReader has quadratic ReDoS on malformed TEI blocks
Affects safetySource GCVE Database
Not known to be exploited · CVSS 6.3 Medium : upgrade to 3.8.1_2 when convenient.
Data as of 30 Oct 2026, 07:30 UTC
- Patch
- Available – fixed in 3.8.1_2
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:NExploitation evidence
Disclosed: evidence found.
CVE published 2 Sep 2026
Detectable: no evidence on record.
No public nuclei template indexed
Weaponized: no evidence on record.
No public exploit code indexed in Metasploit or Exploit-DB
Exploited in the wildExploited: no evidence on record.
Not in CISA KEV and no source reports exploitation
Observed by OffSeq MirageSeen by Mirage: no evidence on record.
No attack traffic recorded by OffSeq Mirage sensors
A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 29 Oct 2026.
What to do
Upgrade safety to 3.8.1_2.
Affected software
| Product | Affected | Fixed in |
|---|---|---|
Homebrewsafetypkg:brew/safetyOther threats | Affected
| Fixed in
|
Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.
Description
### Summary `Pl196xCorpusReader` still parses whole TEI blocks with multiple lazy regexes over attacker-controlled text. A malformed file with many opening tags and no matching closing tags forces repeated rescans and produces quadratic CPU growth in public reader APIs. ### Details - **Vulnerability type:** Regular-expression denial of service - **Affected component:** `nltk.corpus.reader.pl196x.TEICorpusView.read_block` and `Pl196xCorpusReader` public methods - **Affected versions:** Published `3.9.4` and current source `v3.10.0-rc2` both reproduced. - **Patched versions:** Not yet patched - **Root cause:** Lazy `.*?` whole-block regexes rescan untrusted XML-like blocks from each opening-tag position. The parser uses regexes for paragraphs, sentences, and word tags across the whole `<text>` block. When the attacker supplies many unmatched opening tags, each attempt scans toward the end of the block and fails, then restarts from the next opening tag. There is near four-times runtime growth each time the number of malformed `<p>` tags doubled, through normal public calls such as `words()` and `tagged_words()`. ### PoC **Preconditions** - The application parses attacker-influenced PL196X or TEI-like corpus files through public reader APIs. **Steps** 1. Create a corpus file with a valid header followed by a `<text>` block that contains many opening tags and no matching closing tags. 2. Instantiate `Pl196xCorpusReader` on that corpus. 3. Call `words()` or `tagged_words()` and measure elapsed time as the malformed tag count doubles. 4. Observe near quadratic growth instead of near-linear behavior. **Minimal reproducible excerpt** ```text size=1000 0.014s size=2000 0.057s size=4000 0.231s size=8000 0.927s ``` ### Impact A consumer that accepts attacker-influenced corpus files can be forced into heavy CPU use and parser-thread stalling before the application concludes the input contains no valid content. ### Remediation Replace the whole-block lazy-regex parser with a linear parser or bounded tokenizer, and add regression tests that assert near-linear behavior on malformed inputs with many unmatched tags.
References
- github.com/nltk/nltk/security/advisories/GHSA-8mpw-7fpc-4gqj (opens in a new tab)
- nvd.nist.gov/vuln/detail/CVE-2026-81725 (opens in a new tab)
- github.com/nltk/nltk/commit/7808692d451b962711005d954859bb83aabcf8fa (opens in a new tab)
- github.com/nltk/nltk (opens in a new tab)
- github.com/nltk/nltk/releases/tag/v3.10.3 (opens in a new tab)
- github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-3752.yaml (opens in a new tab)
- vulncheck.com/advisories/nltk-before-3.10.3-regular-expression-denial-of-service-via-pl196xcorpusreader (opens in a new tab)