GitHub Advisoryadvisory · PyPI
GHSA-p4gq-832x-fm9v Natural Language Toolkit (NLTK): URL-Encoded Path Traversal in nltk.data.load() Allows Arbitrary Local File Read
HIGH
Official page ↗
- Aliases
- CVE-2026-54293
- Ecosystem
- PyPI
- Packages
- nltk
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Weaknesses
- CWE-22
- Reviewed
- 2026-06-16
Affected packages
• PyPI nltk: < 3.10.0 → fixed in 3.10.0
Description
Summary
nltk.data.load() in NLTK is vulnerable to path traversal via URL-encoded path separators and traversal segments when using the nltk: URL scheme. The unsafe-path regex check is performed before url2pathname() decodes the %xx sequences (a classic decode-after-check / TOCTOU-style flaw), allowing an attacker to bypass the protection documented in NLTK's SECURITY.md and read arbitrary files from the filesystem.
While literal traversal strings such as ../../../etc/passwd are correctly blocked, encoded variants such as %2fetc%2fpasswd, %2e%2e%2f..., and ..%2f..%2f slip past the regex and are subsequently decoded into a real filesystem path.
Affected Component
nltk/data.py — find(), normalize_resource_url(), and the _UNSAFE_NO_PROTOCOL_RE regex check.
Relevant occurrences:
data.py L650–L653 — final path constructed from url2pathname(resource_name) after checks
data.py L54–L69 — _UNSAFE_NO_PROTOCOL_RE operates only on the undecoded string
data.py L219–L245 — normalize_resource_url() for nltk: scheme contributes to decode-after-check
data.py L615–L618 — defense-in-depth traversal check also operates on undecoded input
Root Cause
The regex _UNSAFE_NO_PROTOCOL_RE is matched against the raw resource string. Path normalization via url2pathname() happens later, so any percent-encoded / (%2f) or . (%2e) is invisible to the regex but becomes active in the final path.
Proof of Concept
```
"""
NLTK Arbitrary File Read via URL-Encoded Path Traversal
=======================================================
Bypasses _UNSAFE_NO_PROTOCOL_RE security regex in nltk/data.py
by URL-encoding path separators and traversal components.
Affected: NLTK 0:
print(" Status: VULNERABLE (url2pathname decodes after regex check)")
else:
print(" Status: Not vulnerable")
print("=" * 51)
if __name__ == "__main__":
main()
```
Impact
Arbitrary local file read whenever attacker-controlled input reaches nltk.data.load(). Realistic targets include:
/etc/passwd, /etc/shadow (if readable)
/proc/self/environ — leaks environment variables, often containing API keys, DB credentials, cloud secrets
Application source code and configuration files
Cloud metadata, deployment secrets, SSH keys
This is directly relevant to web applications, hosted notebook services, multi-tenant ML pipelines, and CI/CD systems that pass untrusted resource identifiers into NLTK. NLTK's SECURITY.md explicitly places path traversal within the scope of its protection model, so this is a documented security boundary being broken.
fix
https://github.com/nltk/nltk/pull/3575
Related
Alias · CVE (1)
- CVE-2026-54293 NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in… vulnerability
Weakness · CWE (1)
- CWE-22 Improper Limitation of a Pathname to a Restricted Directory weakness
References
- https://github.com/nltk/nltk/security/advisories/GHSA-p4gq-832x-fm9v web
- https://nvd.nist.gov/vuln/detail/CVE-2026-54293 advisory
- https://github.com/nltk/nltk/pull/3575 web
- https://access.redhat.com/errata/RHSA-2026:42644 web
- https://access.redhat.com/security/cve/CVE-2026-54293 web
- https://bugzilla.redhat.com/show_bug.cgi?id=2491486 web
- https://github.com/nltk/nltk package
- https://github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-2078.yaml web
- https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-54293.json web