NLTK versions before 3.10.0 contain a path traversal vulnerability in FramenetCorpusReader and NKJPCorpusReader that allows attackers to…
VulnCheck·CWE-73·Published 2026-08-22
NLTK versions before 3.10.0 contain a path traversal vulnerability in FramenetCorpusReader and NKJPCorpusReader that allows attackers to parse XML files outside the corpus root by supplying unsafe selectors or poisoned index state. Attackers can exploit frame_by_name, doc, lu, and header methods with crafted parameters to read arbitrary XML files accessible to the application.
NLTK versions before 3.10.0 contain a path traversal vulnerability in FramenetCorpusReader and NKJPCorpusReader that allows attackers to parse XML files outside the corpus root by supplying unsafe selectors or poisoned index state. Attackers can exploit frame_by_name, doc, lu, and header methods with crafted parameters to read arbitrary XML files accessible to the application.
NLTK versions before 3.10.0 contain a path traversal vulnerability in FramenetCorpusReader and NKJPCorpusReader that allows attackers to parse XML files outside the corpus root by supplying unsafe selectors or poisoned index state. Attackers can exploit frame_by_name, doc, lu, and header methods with crafted parameters to read arbitrary XML files accessible to the application.
### Summary Published `nltk==3.9.4` still contains several XML-reader entrypoints that build parser paths from caller-controlled selectors or trusted-looking index state without preserving the corpus-root boundary. ### Details - **Vulnerability type:** Path traversal and trusted-root bypass - **Affected component:** `FramenetCorpusReader.frame_by_name`, `FramenetCorpusReader.doc`, `FramenetCorpusReader.lu`, `NKJPCorpusReader.header` - **Affected versions:** Published `3.9.4` reproduced. Current source `v3.10.0-rc2` acted as a negative control and blocked the same payloads. - **Patched versions:** Patched in version 3.10.0, which includes the path-safety rejections seen in the release candidate. - **Root cause:** Stable reader paths still construct raw XML filenames from unsafe selectors, poisoned index state, or unsafe file identifiers. I confirmed four public stable entrypoints return parsed outside-root content: a parent-segment traversal frame name, a poisoned fulltext index filename, a poisoned LU id, and an unsafe NKJP header file identifier. Current source rejects the same payloads with explicit path-safety errors, which shows the bug is real but version-scoped to the published stable package. ### PoC **Preconditions** - The application exposes FrameNet or NKJP reader APIs while trusting NLTK to keep XML parsing inside a corpus root. **Steps** 1. Create a minimal FrameNet or NKJP corpus root and place attacker-chosen XML files outside that root. 2. Feed unsafe selectors or poisoned index state into the relevant public stable `3.9.4` APIs. 3. Observe `frame_by_name`, `doc`, `lu(...).exemplars`, or `header` return parsed outside-root values. 4. Run the same payloads against current source and observe explicit path-safety rejections. **Minimal reproducible excerpt** ```text framenet_frame_definition FRAME_LEAK framenet_doc_text DOC_LEAK framenet_lu_text LU_LEAK nkjp_header_title HEADER_LEAK ``` ### Impact Applications that process attacker-influenced FrameNet or NKJP corpus selectors or state can be made to parse XML outside the trusted corpus root through normal public reader responses. ### Remediation Keep these reader paths on the same root-confinement model as `CorpusReader.open()` and `nltk.pathsec`. Reject unsafe path components before constructing filenames from frame names, document filenames, LU ids, or NKJP file identifiers. ### Resources - https://github.com/nltk/nltk/blob/3.9.4/nltk/corpus/reader/framenet.py#L1366-L1369 - https://github.com/nltk/nltk/blob/3.9.4/nltk/corpus/reader/framenet.py#L1456-L1460 - https://github.com/nltk/nltk/blob/3.9.4/nltk/corpus/reader/framenet.py#L1803-L1810 - https://github.com/nltk/nltk/blob/3.9.4/nltk/corpus/reader/nkjp.py#L96-L103 - https://github.com/nltk/nltk/blob/3.9.4/nltk/corpus/reader/nkjp.py#L251-L256 - https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/corpus/reader/framenet.py#L1388-L1399 - https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/corpus/reader/nkjp.py#L96-L128
| Version | Type | Source | Base | Exp | Impact | Vector |
|---|---|---|---|---|---|---|
| 3.1 | Primary | NVD | 7.5 | 3.9 | 3.6 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Primary | NVD | 5.9 | 2.2 | 3.6 | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Primary | cve.org | 5.9 | — | — | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Primary | cve.org | 5.9 | — | — | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Secondary | GHSA | 5.9 | — | — | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 3.1 | Secondary | NVD | 5.9 | 2.2 | 3.6 | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 4.0 | Primary | cve.org | 8.2 | — | — | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Primary | cve.org | 8.2 | — | — | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Secondary | GHSA | 8.2 | — | — | CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Secondary | ENISA EUVD | 8.2 | — | — | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Secondary | NVD | 8.2 | — | — | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X |