← Back to Feed CACHED · 2026-08-24 02:18:32 · CACHE_KEY CVE-2026-62384
CVE-2026-62384 · CWE-22 · Disclosed 2026-08-22

NLTK versions before 3.10.2 contain a symlink-based sandbox bypass in FramenetCorpusReader

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Like leaving a treasure-map bookmark inside a library book that leads the librarian to read your diary instead

CVE-2026-62384 affects NLTK versions before 3.10.2. The flaw lives in FramenetCorpusReader — specifically the frame_by_name(), _lu_file(), and doc() methods. An attacker who can write to the corpus subdirectory on disk can plant a symlink whose name contains no path separators. When the reader processes that filename, it passes the lexical path-validation check (nltk.pathsec) but the OS resolves the symlink to a file outside the corpus root, letting the attacker read arbitrary XML-parseable files. The affected scope is NLTK < 3.10.2, fixed in 3.10.2.

The vendor labels this HIGH 7.5 with CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N. That vector is misleading. The attack requires the ability to create symlinks inside the corpus directory on the local filesystem — that is fundamentally a local-access prerequisite, not a network one. The only plausible remote vector is tricking a user into installing a malicious corpus package that embeds symlinks, which is a supply-chain social-engineering step the CVSS doesn't price in. The confidentiality impact is further limited to files that are valid XML. No integrity or availability impact exists. The vendor severity overstates the real-world risk.

"Local symlink trick in a niche NLP corpus reader, not the network-facing RCE the CVSS implies"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Gain write access to NLTK corpus directory

The attacker needs filesystem write access to the directory where NLTK stores corpus data (typically ~/nltk_data/corpora/framenet_v17/ or a custom path). This can be achieved via local shell access, or by convincing the victim to install a trojanized NLTK corpus package that embeds symlinks. On multi-user research servers, a co-tenant with write access to a shared corpus directory could also reach this step.
Conditions required:
  • Local or shared filesystem write access to the NLTK corpus directory
  • Knowledge of the corpus directory path on the target
Where this breaks in practice:
  • Requires prior compromise of the host or social engineering the user into installing a malicious corpus
  • On single-user workstations (the majority of NLTK installs), this requires the attacker to already be on the box — at which point they can likely read files directly
  • Shared corpus directories are uncommon in production; most deployments use per-user ~/nltk_data
Detection/coverage: File-integrity monitoring (e.g., OSSEC, Wazuh) on the corpus directory would flag unexpected symlink creation.
STEP 02

Plant symlink in corpus subdirectory

The attacker creates a symlink inside the FrameNet corpus subdirectory (e.g., frame/) whose filename contains no path separators (e.g., evil.xml -> /etc/passwd). The name must be crafted so that frame_by_name() or doc() will attempt to open it. Because pathsec validates the path lexically without resolving symlinks, the check passes.
Conditions required:
  • Symlink creation capability (on Windows this requires SeCreateSymbolicLinkPrivilege or Developer Mode)
  • Target file must be XML-parseable for data to be extracted meaningfully
Where this breaks in practice:
  • On Windows, unprivileged symlink creation is disabled by default — Developer Mode or admin rights required
  • The target file must parse as valid XML, limiting what can actually be exfiltrated (e.g., /etc/shadow is not XML)
  • Tar/zip extraction in recent Python versions and NLTK >= 3.9.4 may strip symlinks from corpus archives
STEP 03

Trigger corpus read via application

The attacker must cause the application to call frame_by_name(), _lu_file(), or doc() on the FramenetCorpusReader with input that resolves to the planted symlink. In an interactive research session this might happen naturally; in a production NLP service, it would require the service to expose FrameNet lookup to user-controlled input, which is rare.
Conditions required:
  • Application uses FramenetCorpusReader (a niche corpus reader for the FrameNet lexical database)
  • Application calls one of the three vulnerable methods with attacker-influenced input
Where this breaks in practice:
  • FrameNet is an academic linguistic resource — few production services expose FrameNet queries to untrusted users
  • Most NLTK production use cases involve tokenization, POS tagging, or sentiment — not FrameNet corpus reading
  • If the application hardcodes corpus queries, the attacker cannot direct which file is read
Detection/coverage: Application-level logging of corpus reader method calls would surface unexpected frame lookups.
STEP 04

Exfiltrate file contents

The FramenetCorpusReader parses the symlinked file as XML and returns structured data to the caller. The attacker must have a channel to observe the output — either direct shell access (in which case they could just cat the file), or the application must return the parsed data to the network. The exfiltrated content is filtered through an XML parser, so non-XML files produce errors rather than data.
Conditions required:
  • A return channel for the parsed data (screen output, API response, logs)
  • Target file must be well-formed XML
Where this breaks in practice:
  • If the attacker already has shell access to read corpus dirs, they can read most target files directly without this CVE
  • XML-only parsing dramatically limits useful exfiltration targets
  • Error output from malformed XML might leak partial data but is unreliable
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo known exploitation. Not listed on CISA KEV. No campaigns or threat-actor use reported as of 2026-08-24.
Proof of ConceptNo public PoC identified. The SecureWithUmer/CVE-2026-PoCs repo does not appear to include this CVE. Exploitation is conceptually simple (create a symlink) but weaponization against a remote target is non-trivial.
EPSS Score0.00657 (≈0.66%) — low probability of exploitation in the next 30 days. Bottom quartile.
KEV StatusNot listed. No CISA KEV entry as of 2026-08-24.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N — 7.5 HIGH. noisgate assessment: AV:N is inaccurate; realistic vector is closer to AV:L given the symlink-creation prerequisite.
Affected VersionsNLTK < 3.10.2. All prior versions with FramenetCorpusReader and pathsec sandbox are vulnerable.
Fixed VersionNLTK 3.10.2 (PyPI)
Exposure DataNLTK has ~50M+ monthly PyPI downloads, but the vast majority are dev/research workstations and CI environments, not internet-facing services. FramenetCorpusReader is a small fraction of NLTK usage. No Shodan/Censys/GreyNoise signatures relevant — this is a library, not a listening service.
Disclosure Date2026-08-22
ReporterNot publicly attributed. Part of a batch of NLTK pathsec bypass findings (CVE-2026-62383, CVE-2026-62384, CVE-2026-62385, CVE-2026-65915).
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (4.0/10)

The single most decisive factor driving this downgrade is the mislabeled attack vector: exploiting this CVE requires local filesystem write access to plant symlinks in the corpus directory, yet the vendor CVSS claims AV:N/PR:N. Once corrected to AV:L, the base score drops below 6.0, and the niche scope of FramenetCorpusReader plus XML-only read constraint compress real-world impact further.

HIGH Vulnerability mechanics and affected versions
HIGH Friction assessment (local access requirement)
MEDIUM Absence of in-the-wild exploitation (only 2 days since disclosure)

Why this verdict

  • AV:N is wrong — this is a local-access bug. The attacker must create symlinks on the target filesystem inside the corpus directory. The only remote path is via a trojanized corpus package, which is a separate supply-chain social-engineering attack not captured in the CVSS.
  • FramenetCorpusReader is niche. FrameNet is an academic linguistics dataset. The fraction of NLTK's 50M+ monthly installs that actively use FramenetCorpusReader in production services exposed to untrusted input is vanishingly small — likely well under 1%.
  • XML-only read limits blast radius. The exfiltrated file must parse as valid XML. High-value targets like /etc/shadow, database credentials files, and most config files are not XML, severely limiting what an attacker can steal.
  • Role multiplier: NLTK is a library, not infrastructure. It does not occupy any high-value role (not an IdP, hypervisor, backup agent, network edge, CI/CD server, or security agent). In its most common deployment — data-science workstations and Jupyter notebooks — a local attacker who can write to ~/nltk_data already has equivalent or greater read access. In rare ML-pipeline server deployments, the FramenetCorpusReader is unlikely to be in the code path. No high-value-role floor applies.
  • No exploitation signals. Zero KEV listing, no known PoCs, EPSS at 0.66%. Two days post-disclosure with no attacker interest.

Why not higher?

Upgrading to HIGH would require either a genuine unauthenticated remote attack path or exploitation in a high-value-role component. Neither applies: the network vector is a CVSS labeling error (symlink creation is local), FramenetCorpusReader is an academic corpus reader not found in identity/infrastructure roles, and the read-only XML-constrained impact does not reach code execution or domain compromise.

Why not lower?

Despite heavy friction, this is a real sandbox bypass in a widely-installed library (50M+ downloads/month). A trojanized corpus package distributed through a compromised NLTK data mirror *could* weaponize this without direct host access. The confidentiality impact on XML-formatted files (which includes many application configs, Maven POMs, Spring configs, and .csproj files) is non-trivial. Dropping to LOW would undercount the supply-chain angle.

05 · Compensating Control

What to do — in priority order.

  1. Upgrade NLTK to 3.10.2 — The definitive fix. Run pip install --upgrade nltk>=3.10.2 across all environments. Since this is assessed as MEDIUM, the noisgate remediation SLA gives you 365 days, but given the trivial upgrade path, aim to roll it into your next dependency-update cycle.
  2. Restrict write access to NLTK corpus directories — Ensure ~/nltk_data and any shared corpus paths are owned by the application user with mode 0755 (not world-writable). On shared research servers, use per-user corpus roots. This eliminates the symlink-planting prerequisite entirely.
  3. Pin corpus data sources — If you use nltk.download() in CI/CD or automated pipelines, pin to the official NLTK data server and verify checksums. Do not accept corpus packages from untrusted mirrors or user uploads.
  4. Enable file-integrity monitoring on corpus directories — Deploy FIM (OSSEC, Wazuh, auditd) rules to alert on symlink creation inside NLTK corpus directories. This provides detection of exploitation attempts.
What doesn't work
  • WAF / network IDS — this is not a network-exploitable vulnerability; no HTTP payload or network signature exists to detect or block.
  • Sandboxing NLTK with pathsec.ENFORCE=True — that is exactly the sandbox being bypassed by this CVE; it does not help until you upgrade to 3.10.2.
  • Python virtual environments — venvs isolate packages but do not restrict filesystem symlink creation within the corpus directory.
06 · Verification

Crowdsourced verification payload.

Run this script on any host where NLTK is installed. It checks the installed NLTK version against the fix. No special privileges required. Invoke with: python check_cve_2026_62384.py

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
"""Check for CVE-2026-62384: NLTK FramenetCorpusReader symlink sandbox bypass.
Affected: NLTK < 3.10.2
Fixed: NLTK >= 3.10.2
"""
import sys

try:
    import nltk
except ImportError:
    print("UNKNOWN - NLTK is not installed on this system.")
    sys.exit(2)

try:
    from packaging.version import Version
except ImportError:
    # fallback to distutils (deprecated but available in older Pythons)
    from distutils.version import LooseVersion as Version

installed = nltk.__version__
fixed = "3.10.2"

try:
    if Version(installed) < Version(fixed):
        print(f"VULNERABLE - NLTK {installed} is installed (fix: >= {fixed}). CVE-2026-62384 applies.")
        sys.exit(1)
    else:
        print(f"PATCHED - NLTK {installed} is installed (fix: >= {fixed}). CVE-2026-62384 does not apply.")
        sys.exit(0)
except Exception as e:
    print(f"UNKNOWN - Could not compare versions: {e}")
    sys.exit(2)
07 · Bottom Line

If you remember one thing.

TL;DR
This is a MEDIUM (4.0) after noisgate reassessment — the vendor's HIGH 7.5 is inflated by an incorrect network attack vector. The real prerequisite is local filesystem write access, and the impact is confined to reading XML files via a niche academic corpus reader. No mitigation SLA applies at MEDIUM — go straight to the 365-day noisgate remediation SLA by upgrading NLTK to 3.10.2 (pip install --upgrade nltk>=3.10.2) during your next scheduled dependency refresh. If you run shared multi-tenant research or ML-pipeline servers with writable corpus directories, tighten directory permissions this week as a compensating control. There is no active exploitation, no KEV listing, and EPSS is under 1% — this is a backlog item, not a fire drill.

Sources

  1. OffSeq Threat Radar — CVE-2026-62384
  2. GitLab Advisory Database — NLTK CVE-2026-12074 (related FrameNet path traversal)
  3. NLTK GitHub Releases
  4. NLTK Zip-Slip Fix PR #3468
  5. PyPI — NLTK
  6. NLTK Official Data Installation Guide
  7. PyPI Download Stats — NLTK
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.