Sep 8, 2026·6 min read·5 visits
NLTK versions prior to 3.10.3 fail to validate user-supplied corpus root paths against the internal pathsec sandbox during CorpusReader initialization. This oversight allows attackers to perform local directory listings and unauthorized reads on arbitrary files and SQLite databases.
A critical logical flaw in the Natural Language Toolkit (NLTK) allows attackers to bypass the application-level directory sandbox. This vulnerability enables unauthenticated directory enumeration and arbitrary local file or SQLite database access.
The Natural Language Toolkit (NLTK) is an industry-standard Python library used extensively for natural language processing, corpus management, and text analysis. In environments where untrusted parties can configure linguistic pipelines or supply corpus metadata, NLTK relies on an application-level path sandbox implementation (nltk.pathsec) to isolate local file access.
This security sandbox acts as a logical barrier, restricting corpus load and read operations strictly to authorized system paths, such as the predefined nltk_data directory. When security enforcement is globally enabled (pathsec.ENFORCE = True), any operational request targeting an out-of-bounds directory path should trigger an access-denied exception.
A systemic security gap was discovered in the way the base CorpusReader class and several specialized subclasses initialize geographic and semantic assets. Specifically, the base constructor processes user-supplied root path strings into directory pointer structures without applying validation rules against the active sandbox context. Consequently, this exposes sensitive local files to unauthorized access and analysis.
The root cause of this vulnerability lies in the lack of path validation inside CorpusReader.__init__ and subsequent direct usage of unvalidated paths in disk operations. When instantiating CorpusReader, the program accepts a raw root string parameter representing the filesystem location of the linguistic dataset. The constructor converts this parameter to a PathPointer object, such as a FileSystemPathPointer or ZipFilePathPointer, without ensuring the target path resides within the restricted boundaries.
While subsequent read operations theoretically leverage the sandboxed file-opening wrapper (nltk.pathsec.open), several corpus reader subclasses execute eager local operations immediately upon construction. For example, the PanLexLiteCorpusReader attempts to query a local database via Python's default, unsandboxed sqlite3.connect() function. This bypasses the NLTK path restriction mechanisms entirely because standard library calls are not subjected to nltk.pathsec interception.
Similarly, the LinThesaurusCorpusReader subclass processes thesaurus mappings directly using the built-in open() function on derived filesystem paths. Furthermore, utility functions like find_corpus_fileids use standard filesystem functions (os.walk) to identify corpus structures before the base class verification logic executes. Because these structures resolve targets using unvalidated root paths, an attacker can trigger information disclosure or arbitrary database interactions prior to execution control checks.
An analysis of the underlying codebase reveals the discrepancy between the vulnerable design and the security fix implemented in version 3.10.3.
# Vulnerable constructor implementation in NLTK <= 3.10.2
def __init__(self, root, fileids, encoding="utf8", tagset=None):
# The root string was processed without checking the sandbox status
if isinstance(root, str) and not isinstance(root, PathPointer):
m = re.match(r"(.*\.zip)/?(.*)$|", root)
# Path pointer objects are built immediatelyIn the patched version, the constructor actively checks pathsec.ENFORCE and applies a validation routine to block illegitimate paths:
# Patched constructor implementation in NLTK >= 3.10.3
def __init__(self, root, fileids, encoding="utf8", tagset=None):
# Core protection logic added:
if pathsec.ENFORCE and isinstance(root, str):
pathsec.validate_path(root, context="CorpusReader.__init__")
if isinstance(root, str) and not isinstance(root, PathPointer):
m = re.match(r"(.*\.zip)/?(.*)$|", root)For subclasses like PanLexLiteCorpusReader, the vulnerability allowed direct access to SQLite files using unvalidated database paths. The patch intercepts the directory configuration path before passing it to the database driver:
# Patched database initialization in panlex_lite.py
def __init__(self, root):
from nltk.pathsec import validate_path
db_path = os.path.join(root, "db.sqlite")
# Restrict SQLite connection targets using validate_path
# 'required_root' suppresses symbolic link traversal attempts
validate_path(db_path, context="PanLexLiteCorpusReader", required_root=root)
self._c = sqlite3.connect(db_path).cursor()Exploitation of this vulnerability requires an application configuration where user inputs can directly or indirectly influence the corpus root parameter passed to NLTK corpus readers. This scenario is common in multi-tenant workspaces, online processing notebooks, and data processing pipelines that dynamically load user-submitted metadata.
An attacker can trigger directory walking on restricted host paths using find_corpus_fileids. When a target system exposes this file-scanning function, an attacker can specify a sensitive path, such as the system configuration folder, to obtain a structured directory index.
# Proof of concept demonstrating out-of-sandbox directory scanning
from nltk.corpus.reader.util import find_corpus_fileids
from nltk.data import FileSystemPathPointer
# Construct an arbitrary pointer to check restricted folders
root_pointer = FileSystemPathPointer("/etc")
# Scanning executes os.walk directly, bypassing sandbox boundaries
fileids = find_corpus_fileids(root_pointer, r".*")
print(fileids)In a second exploitation scenario, an attacker can target the database connection routine of PanLexLiteCorpusReader. If the root variable points to an arbitrary location containing an SQLite database structure, the application will initialize an active SQLite connection session, allowing database interactions without satisfying path restrictions.
The security impact of CVE-2026-79674 is categorized as High, as reflected by its CVSS v4.0 score of 8.8. Successful exploitation allows complete local directory mapping and unauthorized read access to accessible host system files.
In containerized or restricted multi-tenant environments, this bypass allows the extraction of database credentials, access tokens, and environment parameters from the container filesystem. Because the vulnerability allows raw database initiation with arbitrary SQLite files, an attacker could interact with external sqlite structures, leading to unauthorized information extraction.
Since this exploit is purely logical and relies on missing path verification steps, exploitation attempts do not trigger standard memory corruption defense mechanisms. The lack of active public exploits decreases immediate risk, but the ease of implementation makes manual exploitation highly viable if systems remain unpatched.
To mitigate CVE-2026-79674, system administrators and developers must upgrade the nltk package to version 3.10.3 or higher. This update resolves the logical path validation gaps in the CorpusReader core module and structural utilities.
When immediate library upgrades are not feasible, applications must implement path sanitization routines to ensure input paths resolve to authorized locations before initiating NLTK components. Using Python's pathlib.Path.resolve() method assists in verifying that resolving paths remain within safe boundaries.
from pathlib import Path
ALLOWED_ROOT = Path("/var/data/nltk_data").resolve()
def validate_user_input(input_path_str):
target_path = Path(input_path_str).resolve()
if not target_path.is_relative_to(ALLOWED_ROOT):
raise PermissionError("Path is outside the authorized data root")
return target_pathCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
nltk nltk | < 3.10.3 | 3.10.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-73 (External Control of File Name or Path) |
| Attack Vector | Network |
| CVSS v3.1 Score | 8.2 (High) |
| CVSS v4.0 Score | 8.8 (High) |
| EPSS Score | 0.00226 |
| CISA KEV Listed | False |
| Exploit Status | poc |
The software allows user input to control path and filename resolutions, bypassing intended access controls.
A command-line option injection vulnerability in GitPython allows low-privilege or unauthenticated actors to read arbitrary local files. The flaw resides in the TagReference.create() function, which fails to evaluate positional arguments against the library's unsafe-option denylist, enabling the execution of native git commands with injected option flags.
GitPython prior to version 3.1.59 contains a path traversal vulnerability via parameter injection. The clone denylist did not restrict the `--separate-git-dir` option, allowing attackers to write repository metadata to arbitrary system paths.
CVE-2026-72925 is a critical vulnerability in the SWC HTML minifier (@swc/html and swc_html_minifier) where safe Unicode-escaped characters in embedded JSON script tags are normalized into raw, unescaped characters during optimization, causing browser-side HTML injection and Cross-Site Scripting.
An improper integrity verification vulnerability exists in the Natural Language Toolkit (NLTK) library up to and including version 3.9.4. The library's download utility writes remote ZIP packages directly to disk and extracts their contents onto the filesystem before executing cryptographic checksum validation. An attacker capable of intercepting or manipulating the download stream can exploit this behavior to perform arbitrary file writes, directory traversal, or execute untrusted serialized content.
A critical Server-Side Request Forgery (SSRF) bypass vulnerability exists in CodeWhale before version 0.8.64 (and version 0.8.41 in the 0.8.x branch) due to a Time-of-Check to Time-of-Use (TOCTOU) bug in its DNS pre-flight validation mechanism. By returning a temporary resolution failure during validation and subsequently resolving to restricted IPs during HTTP execution, attackers can bypass security rules.
An argument injection vulnerability in CodeWhale (CVE-2026-75912 / GHSA-c6mw-8xh8-gpq6) allows unauthenticated remote attackers to execute arbitrary option commands on the git binary. By passing malicious command-line flags inside git_blame and git_show tool helper functions, an attacker can bypass typical access controls to read arbitrary local system files via the underlying git process.