Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

CVE-2026-12243 — nltk

HIGHFix: nltk/nltk#3522

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()

Also known asGHSA-m42h-3232-vpv3PYSEC-2026-597
Published
Jun 30, 2026
Updated
Aug 13, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Aug 13, 2026 · OSV.dev, FIRST.org (EPSS)

Real-World Exposure

1 pkg affected
🐍nltk

Real-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

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPInltkall versions3.10.0pip install --upgrade 'nltk==3.10.0'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    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.

  2. 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.

  3. 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.

Red HatImportant

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…

Workaround published by Red Hat
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)
ProductFixed inAdvisory
Red Hat OpenShift AI 2.25rhoai/odh-ta-lmes-job-rhel9:1787330903RHSA-2026:65126
Red Hat OpenShift AI 3.4rhoai/odh-llama-stack-core-rhel9:1786635926RHSA-2026:60520

Frequently Asked Questions

# 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): r
O3 Security · Impact-Aware SCA

Is CVE-2026-12243 in your dependencies?

Find it across PyPI, including transitive dependencies.