Listen to this Post
NLTK (Natural Language Toolkit) versions prior to 3.10.3 contain a path sandbox bypass vulnerability in corpus-reader constructors. The core issue is that `CorpusReader.__init__()` converts a string `root` into a `FileSystemPathPointer` without any validation from the `nltk.pathsec` sandbox.
Affected readers like `LinThesaurusCorpusReader` and `PanLexLiteCorpusReader` then use built-in `open()` or `sqlite3.connect()` directly on derived paths. As a result, the constructor path never passes through the sandbox guard that `pathsec.open()` enforces. The PoC demonstrates that while `pathsec.open()` correctly blocks access to a file outside the sandbox, the two vulnerable readers succeed in reading outside the root in the same process.
This vulnerability allows attackers to supply arbitrary corpus root paths to these constructors to access filesystem content and SQLite databases beyond the intended `pathsec` sandbox boundary. The flaw is reliably triggerable by caller-controlled path input and requires no special privileges inside the process.
DailyCVE Form:
Platform: NLTK
Version: <3.10.3
Vulnerability: Path Sandbox Bypass
Severity: High (8.2 CVSS)
date: 2026-08-25
Prediction: Patch available in 3.10.3
What Undercode Say:
Analytics show this vulnerability affects all NLTK versions before 3.10.3. The exploit is automatable and requires no authentication. Technical details are publicly known, and proof-of-concept code is available. The vulnerability class is CWE-73: External Control of File Name or Path.
Check installed NLTK version python -c "import nltk; print(nltk.<strong>version</strong>)" Verify if vulnerable (versions < 3.10.3) pip show nltk | grep Version Upgrade to patched version pip install --upgrade nltk>=3.10.3
Exploit: (Educational Purposes!)
The following steps demonstrate the sandbox bypass:
- Set `pathsec.ENFORCE = True` to enable the sandbox
- Create a temporary directory with an “outside” file and a SQLite database
- Attempt `pathsec.open()` on the outside file → blocked with `PermissionError`
4. Instantiate `LinThesaurusCorpusReader(str(lin_root))` → uses built-in `open()` to read `simN.lsp`
5. Instantiate `PanLexLiteCorpusReader(str(panlex_root))` → uses `sqlite3.connect()` to read `db.sqlite`
6. Both readers successfully access data outside the sandbox boundaryVulnerable code path (simplified) class CorpusReader: def <strong>init</strong>(self, root): No pathsec validation here! self.root = FileSystemPathPointer(root) class LinThesaurusCorpusReader(CorpusReader): def _read_file(self, path): Direct built-in open() - bypasses sandbox! with open(path) as f: return f.read()
Protection
- Upgrade to NLTK version 3.10.3 or later
- Validate raw string roots before constructing readers
- Route all corpus-root/path handling through `pathsec` or a validated `PathPointer`
– Remove direct `builtins.open()` and `sqlite3.connect(os.path.join(…))` on constructor-derived paths - Apply the official patch from commit `474af1f5a94b1b8d53fc2b6defec3a2ce7633b74`
Impact
A caller can make NLTK read filesystem content outside the intended NLTK data sandbox through public corpus-reader constructors. In the PoC, this includes a local text file and a local SQLite database. The vulnerability exposes data outside the intended trust boundary and requires no special privileges. Attackers can access arbitrary filesystem content and SQLite databases beyond the `pathsec` sandbox boundary.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

