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

CVE-2026-79676: NLTK Path Traversal Vulnerability

CVE-2026-79676 is a path traversal flaw in NLTK that allows attackers to escape trusted data roots via symlinked corpus files. This post explains the technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-79676 Overview

CVE-2026-79676 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) affecting versions before 3.10.3. The flaw resides in NLTK corpus readers that reopen root-derived paths using the built-in open() function instead of the security-aware nltk.pathsec.open() wrapper. This gap allows symbolic links staged inside a trusted data root to escape that root and expose arbitrary files on the host. Attackers who can plant symlinked corpus files under a trusted directory can disclose outside-root content through standard reader methods including channels(), domains(), and synonyms(). The issue is tracked under CWE-22: Improper Limitation of a Pathname to a Restricted Directory.

Critical Impact

Unauthorized disclosure of files outside the trusted NLTK data root through symlink-based path traversal in corpus reader APIs.

Affected Products

  • NLTK (Natural Language Toolkit) versions prior to 3.10.3
  • Python applications embedding NLTK corpus readers that call channels(), domains(), or synonyms()
  • Downstream libraries and services that expose NLTK data roots to untrusted content

Discovery Timeline

  • 2026-08-25 - CVE-2026-79676 published to the National Vulnerability Database
  • 2026-08-25 - Last updated in NVD database

Technical Details for CVE-2026-79676

Vulnerability Analysis

NLTK enforces a trusted data root to constrain where corpus readers may access files. The library provides nltk.pathsec.open() as a hardened file-opening primitive that validates paths against the configured root before returning a handle. Several corpus readers accept a root-derived path, perform validation once, and then reopen the resolved path with Python's built-in open().

The secondary open call does not re-check the path against the trusted root. If the resolved path is a symbolic link that points outside the root, the built-in open() follows the symlink and reads the linked target. Reader methods such as channels(), domains(), and synonyms() propagate the returned data back to the caller, enabling disclosure of file contents that should be inaccessible.

Root Cause

The root cause is inconsistent use of the security-aware path opener across corpus reader code paths. nltk.pathsec.open() centralizes validation and symlink handling, but reopen sites bypassed it in favor of the built-in open(). This violates the principle of complete mediation for file access and leaves a Time-of-Check to Time-of-Use gap that a symlink satisfies at the second access.

Attack Vector

Exploitation requires an attacker to stage a malicious file under the trusted NLTK data root. The file is a symbolic link whose target is an arbitrary path on the host filesystem, for example a configuration file, credential store, or private dataset. When an application invokes an affected corpus reader method against the staged corpus, NLTK follows the symlink and returns the target's contents. Attack scenarios include shared multi-tenant systems, container images pre-populated with attacker-controlled corpora, and pipelines that ingest third-party NLTK data bundles.

A verified proof-of-concept is not published in the referenced advisories. See the GitHub Security Advisory GHSA-p4rw-rvv2-7xwr and the VulnCheck Advisory on NLTK for technical details.

Detection Methods for CVE-2026-79676

Indicators of Compromise

  • Symbolic links present inside NLTK data directories such as ~/nltk_data/ or system-wide equivalents whose targets resolve outside those directories.
  • Python processes reading sensitive files including /etc/passwd, SSH keys, or environment files immediately after invoking NLTK corpus reader methods.
  • Corpus bundles obtained from untrusted sources that contain .symlink metadata or unexpected link entries when extracted.

Detection Strategies

  • Enumerate NLTK data roots and flag any entry where os.path.islink() returns true and the resolved target falls outside the configured root.
  • Instrument Python applications to log calls to nltk.corpus.reader methods together with the absolute path of every file opened during the call.
  • Compare installed NLTK versions across hosts against 3.10.3 using software bill of materials data or pip show nltk output.

Monitoring Recommendations

  • Alert on file reads by Python interpreters where the target path is outside declared data directories, using endpoint telemetry or Linux auditd rules on openat syscalls.
  • Monitor package registries and internal artifact repositories for unofficial NLTK corpus archives introduced without review.
  • Track file integrity of NLTK data directories to detect newly added symbolic links.

How to Mitigate CVE-2026-79676

Immediate Actions Required

  • Upgrade NLTK to version 3.10.3 or later across all production, development, and container environments.
  • Audit every NLTK data root for symbolic links and remove any link whose target resolves outside the root.
  • Restrict write permissions on NLTK data directories to trusted administrators and build pipelines only.

Patch Information

The maintainers fixed the issue in NLTK 3.10.3 by routing the affected reopen sites through nltk.pathsec.open(), which validates the resolved path against the trusted root and rejects symlinks that escape it. Refer to the GitHub Security Advisory GHSA-p4rw-rvv2-7xwr for commit references and release notes.

Workarounds

  • Treat all third-party corpus bundles as untrusted and extract them in an isolated environment that rejects symbolic links, for example using tar --no-same-owner --no-same-permissions with a wrapper that strips link entries.
  • Run NLTK-consuming services under a dedicated user with read-only access limited to the corpus directory and no ability to read sensitive host files.
  • Apply mandatory access controls such as AppArmor or SELinux profiles that confine the Python process to specific filesystem paths.
bash
# Upgrade NLTK and verify no symlinks escape the data root
pip install --upgrade 'nltk>=3.10.3'
python - <<'PY'
import os, nltk
root = os.path.expanduser('~/nltk_data')
for dirpath, _, files in os.walk(root):
    for name in files:
        p = os.path.join(dirpath, name)
        if os.path.islink(p):
            target = os.path.realpath(p)
            if not target.startswith(os.path.realpath(root)):
                print('ESCAPING SYMLINK:', p, '->', target)
PY

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.