Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-70626

CVE-2026-70626: NLTK Path Traversal Vulnerability

CVE-2026-70626 is a symlink escape flaw in NLTK that enables local attackers to read arbitrary files outside the corpus root through symlink manipulation. This article covers the technical details, affected versions, security impact, and mitigation strategies.

Published:

CVE-2026-70626 Overview

CVE-2026-70626 is a symlink escape vulnerability in the Natural Language Toolkit (NLTK) affecting versions before 3.9.4. The flaw resides in CorpusReader.open(), where path validation relies on lexical checks rather than resolving symbolic links. A local attacker can place a symlink inside the corpus root that points to a file elsewhere on the filesystem. When NLTK opens that entry, it follows the symlink and returns the contents of arbitrary files the process can read. This weakness is tracked under CWE-59: Improper Link Resolution Before File Access.

Critical Impact

Local attackers can read arbitrary files outside the intended corpus root, exposing credentials, source code, and other sensitive data accessible to the NLTK process.

Affected Products

  • NLTK (Natural Language Toolkit) versions before 3.9.4
  • Python applications and pipelines that instantiate CorpusReader on attacker-influenced directories
  • Multi-tenant data science and NLP environments sharing corpus paths

Discovery Timeline

  • 2026-08-22 - CVE-2026-70626 published to the National Vulnerability Database
  • 2026-08-24 - Last updated in NVD database

Technical Details for CVE-2026-70626

Vulnerability Analysis

NLTK's CorpusReader class exposes an open() method that resolves a requested file name against the configured corpus root. Prior to version 3.9.4, this resolution performed only lexical path checks, comparing string prefixes rather than resolving symbolic links on disk. As a result, an attacker who can write files into the corpus directory can plant a symlink whose target lies outside that directory.

When NLTK later opens that entry, the operating system dereferences the symlink and returns the contents of the target file. The vulnerability requires local access because the attacker must place the symlink within a directory that NLTK will read. Impact scales with the privileges of the process invoking NLTK — services running as elevated users can leak configuration files, private keys, or credentials.

Root Cause

The root cause is missing symlink resolution during path validation. CorpusReader.open() verifies that the requested path appears to live under the corpus root using string operations, without calling os.path.realpath() or an equivalent canonicalization step. Because the check is performed on the lexical path rather than the resolved inode, symlinks bypass the boundary entirely. This pattern maps directly to [CWE-59].

Attack Vector

Exploitation follows a predictable sequence. The attacker first identifies a corpus directory that a target NLTK-based process reads. They then create a symlink inside that directory pointing to a sensitive file such as /etc/shadow, ~/.aws/credentials, or an application secret. When the NLTK application enumerates or opens corpus entries, CorpusReader.open() follows the symlink and returns the target file's contents to the caller. No authentication, network access, or user interaction is required beyond the ability to write to the corpus directory.

No verified public proof-of-concept code is referenced in the advisory. Technical details are available in the GitHub Security Advisory GHSA-r6gq-whwq-mvg9 and the VulnCheck Advisory on Symlink Escape.

Detection Methods for CVE-2026-70626

Indicators of Compromise

  • Symbolic links inside NLTK corpus directories whose targets resolve outside the corpus root
  • Unexpected reads of sensitive files (for example /etc/passwd, SSH keys, cloud credentials) by Python processes hosting NLTK
  • NLTK application logs referencing corpus entries whose names or paths do not match the expected corpus schema

Detection Strategies

  • Enumerate corpus directories and flag any entry where os.path.realpath(entry) does not begin with the canonical corpus root
  • Inventory installed Python packages across build agents, notebooks, and production hosts to identify NLTK versions earlier than 3.9.4
  • Audit code paths that pass user-controlled or shared directories to CorpusReader subclasses

Monitoring Recommendations

  • Monitor file access telemetry for Python interpreters opening files outside declared data directories
  • Alert on creation of symbolic links within directories owned by data science service accounts
  • Track process-level file reads on secret stores and credential files by NLP workloads

How to Mitigate CVE-2026-70626

Immediate Actions Required

  • Upgrade NLTK to version 3.9.4 or later across all environments, including virtualenvs, container images, and CI runners
  • Audit existing corpus directories for pre-existing symlinks pointing outside the corpus root and remove them
  • Restrict write access to corpus directories so that only trusted identities can add files or links

Patch Information

The issue is fixed in NLTK 3.9.4. The fix adds symlink-aware canonicalization when validating paths returned by CorpusReader.open(), ensuring that resolved targets remain under the configured corpus root. Refer to the GitHub Security Advisory GHSA-r6gq-whwq-mvg9 for the authoritative patch notes and affected version ranges.

Workarounds

  • Run NLTK-based services under least-privilege accounts that cannot read sensitive files such as private keys or credential stores
  • Store corpora on read-only mounts or filesystems that disallow symbolic link creation
  • Pre-validate corpus directories by rejecting or removing any entry where the real path escapes the intended root
bash
# Upgrade NLTK to the patched release
python -m pip install --upgrade 'nltk>=3.9.4'

# Verify no symlinks escape the corpus root
find /path/to/corpus -type l -exec sh -c '
  for link; do
    target=$(readlink -f "$link")
    case "$target" in
      /path/to/corpus/*) ;;
      *) echo "ESCAPE: $link -> $target" ;;
    esac
  done
' sh {} +

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.