CVE-2026-12243 is a high-severity (CVSS 7.5) vulnerability in nltk. A fix is available for nltk — see the affected versions and patch details below.
Path Traversal via Percent-Encoding in nltk.data.find() and nltk.data.load()
Real-World Exposure
nltkReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
Summary
nltk.data.load() and nltk.data.find() resolve user-supplied resource names to filesystem paths using url2pathname(), which decodes percent-encoded sequences (e.g. %2e%2e to ..). Path safety checks are performed on the raw, still-encoded string before decoding occurs. An attacker supplying %2e%2e instead of .. bypasses all path validation and reads arbitrary files outside the NLTK data directory.
Vulnerable Code
nltk/data.py - find() function: url2pathname() decodes %2e%2e -> .. AFTER any safety check p = os.path.join(path_, url2pathname(resource_name)) if os.path.exists(p): return FileSystemPathPointer(p)
Proof of Concept
import nltk.data nltk.data.path = ["/home/user/nltk_data"] %2e%2e decodes to .. via url2pathname(), escaping the data dir data = nltk.data.load("%2e%2e/SECRET_credentials.txt", format="raw") print(data) b'AWS_SECRET_KEY=AKIAIOSFODNN7EXAMPLE\nDATABASE_PASS=hunter2\n' All of these bypass path checks and decode identically:
Payload After url2pathname()
%2e%2e/secret ../secret .%2e/secret ../secret %2e./secret ../secret %2E%2E/secret ../secret Root Cause url2pathname() is called after path safety checks, not before. Encoding .. as %2e%2e passes every check, then decodes to a traversal sequence at filesystem access time.
Fix
Decode before checking:
from urllib.parse import unquote resource_name = unquote(resource_name) # decode first, then validate
Impact
An attacker who controls the resource name passed to nltk.data.load() can read any file the process has permission to access - credentials, environment files, SSH private keys, /etc/passwd, /proc/self/environ, application config files, etc. This affects any application that passes user-controlled input to nltk.data.load() or nltk.data.find().
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | nltk | all versions | 3.10.0pip install --upgrade 'nltk==3.10.0' |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for nltk, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update nltk to 3.10.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-12243 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
A path traversal flaw was found in NLTK's resource loading functions (nltk.data.load() and nltk.data.find()). The vulnerability allows arbitrary file reads when an attacker can control the resource_name parameter by using percent-encoded path separators to bypass validation. In Red Hat products where NLTK is bundled…
Do not pass untrusted or user-controlled input directly to nltk.data.load() or nltk.data.find(). Validate and sanitize any resource name parameter before use, rejecting values containing percent-encoded characters (%2f, %2e) or path traversal sequences. As defense-in-depth, set nltk.pathsec.ENFORCE = True in application code to enable file-read restrictions at the open stage (disabled by default).Source: Red Hat security advisory for CVE-2026-12243 (CC BY 4.0)
| Product | Fixed in | Advisory |
|---|---|---|
| Red Hat OpenShift AI 2.25 | rhoai/odh-ta-lmes-job-rhel9:1787330903 | RHSA-2026:65126 |
| Red Hat OpenShift AI 3.4 | rhoai/odh-llama-stack-core-rhel9:1786635926 | RHSA-2026:60520 |
Frequently Asked Questions
Is CVE-2026-12243 in your dependencies?
Find it across PyPI, including transitive dependencies.