NLTK: BllipParser passes caller-supplied model paths to the bllipparser C extension with no pathsec check, enabling
Affects nltkSource GCVE Database
Not known to be exploited · CVSS 7.0 High : upgrade to 3.10.4 soon.
Data as of 14 Nov 2026, 01:05 UTC
Thin evidence
One scorer or none| CNA (VulnCheck) | CVSS 4.0 | 7.0 |
|---|---|---|
| CNA (VulnCheck) | CVSS 3.1 | 6.8 |
- Patch
- Available – fixed in 3.10.4
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:L/SC:N/SI:N/SA:NExploitation evidence
Disclosed: evidence found.
CVE published 13 Nov 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 13 Nov 2026.
What to do
Upgrade nltk to 3.10.4.
Affected software
| Product | Affected | Fixed in |
|---|---|---|
| PyPInltk | 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 `BllipParser` in `nltk/parse/bllip.py` hands caller-supplied filesystem paths to the native `bllipparser` C extension without routing them through NLTK's `pathsec` validation. The constructor parameters `parser_model`, `reranker_features`, and `reranker_weights`, and the alternative `from_unified_model_dir()` entry point, flow directly to the C extension's `load_parser_model()` and `load_reranker_model()` calls, which open and read the given path at the OS level. Any application that passes an attacker-influenced path to this API reads a file of the attacker's choosing from anywhere on the filesystem, outside the NLTK data roots that every other NLTK tool wrapper confines access to. ## Root Cause As of NLTK 3.10.0, `SECURITY.md` documents a centralized I/O security module (`nltk.pathsec`) with strict enforcement enabled by default, under which file-backed resources must resolve inside allowed NLTK data directories. For paths handed to external tools and native extensions that open files themselves, the module provides `validate_tool_path()`, which runs name-safety checks, rejects option-shaped, URL-shaped, and traversal inputs, opens the path with `O_NOFOLLOW` requiring a regular single-linked file, and returns the validated string the caller must use. Every sibling tool wrapper applies it. `BllipParser` applies none of it: the module imports only `ParserI`, `safe_print`, and `Tree`, with zero `pathsec` references, so the three model-path parameters reach the C extension unchecked. The violated invariant is that NLTK tool wrappers must bound caller-supplied native-tool paths to the data roots before the native code opens them. ```text nltk/parse/bllip.py:125-131 BllipParser.__init__ accepts parser_model, reranker_features, reranker_weights (no validation) nltk/parse/bllip.py:164 self.rrp.load_parser_model(parser_model, ...) -> C extension open nltk/parse/bllip.py:166-170 self.rrp.load_reranker_model(features_filename=..., weights_filename=...) -> C extension open nltk/parse/bllip.py:218-255 from_unified_model_dir(model_dir) -> __init__ (no validation) nltk/parse/bllip.py:9-11 imports: ParserI, safe_print, Tree (no pathsec import) ``` ## Impact An application that uses `BllipParser` (requiring the optional `bllipparser` package to be installed) and that passes a model path derived from untrusted input to the constructor or to `from_unified_model_dir()` allows that input to designate an arbitrary filesystem path. The native extension opens and reads the designated file into process memory to parse it as model data. This defeats the pathsec data-root confinement that NLTK applies to all other native-tool model loads. The attacker-controlled path can target files outside the NLTK data directories, for example local configuration or credential files readable by the process. Content disclosure to the attacker depends on how the application surfaces parser errors or results; file existence, size, and open behavior provide an oracle regardless. Because the same unvalidated path also skips the checks that refuse a non-regular file or an over-large model, the attacker can instead designate a FIFO, socket, device, or directory, or an oversized regular file, so the native load blocks or reads unbounded data into memory and the component performing the parse suffers reduced performance or a stalled worker. The primitive demonstrated by source analysis is attacker control of which file the process opens and reads. ## Proof of Concept ```text Requires the optional bllipparser C extension to be installed (pip install bllipparser) so that RerankingParser.load_parser_model is available. No NLTK data download is needed to exercise the path. ``` ```python # An application forwards an untrusted "model" path into BllipParser. from nltk.parse.bllip import BllipParser # Attacker-controlled value reaches the constructor unchanged. untrusted_path = "/etc/passwd" BllipParser(parser_model=untrusted_path) # The bllipparser C extension opens and reads untrusted_path at the OS # level with no NLTK pathsec confinement to the data roots. ``` ```text Structural confirmation without the optional extension installed: $ grep -n "pathsec\|validate_path\|validate_tool" nltk/parse/bllip.py (no output) $ grep -n "validate_tool_path" nltk/tag/crf.py nltk/tag/hunpos.py \ nltk/tag/stanford.py nltk/parse/malt.py nltk/tag/crf.py:140 nltk/tag/crf.py:311 nltk/tag/hunpos.py:111 nltk/tag/stanford.py:85 nltk/tag/stanford.py:137 nltk/parse/malt.py:340 nltk/parse/malt.py:344 BllipParser is the only native-tool wrapper with no validate_tool_path call. ``` ## Attack Chain 1. **Exposure:** An application imports `BllipParser` (exported at `nltk/parse/bllip.py:83` and re-exported at `nltk/parse/__init__.py:47`) and constructs it with a model path influenced by untrusted input. 2. **Control:** The attacker controls the `parser_mo
References
- github.com/nltk/nltk/security/advisories/GHSA-fg9w-wfp5-j933 (opens in a new tab)
- nvd.nist.gov/vuln/detail/CVE-2026-126295 (opens in a new tab)
- github.com/nltk/nltk/commit/fdde6d9ebf5fd612e817b49ec7fecd752802c268 (opens in a new tab)
- github.com/nltk/nltk (opens in a new tab)
- github.com/nltk/nltk/releases/tag/v3.10.4 (opens in a new tab)
- vulncheck.com/advisories/nltk-3.10.0-before-3.10.4-arbitrary-file-read-via-bllipparser-model-paths (opens in a new tab)