Executive brief
NLTK's CorpusReader component is used by applications to safely read files from a restricted corpus directory. Due to improper symlink resolution, an attacker who can place a symlink inside the allowed corpus root can bypass the access control and read arbitrary files on the system, including system configuration files, secrets, and private data. This affects any application that relies on CorpusReader as a security boundary for file access.
Technical details
The vulnerability is a symlink-following (CWE-59) filesystem sandbox bypass in nltk.corpus.reader.api.CorpusReader and nltk.data.FileSystemPathPointer. The vulnerable code performs path normalization via os.path.normpath() and validates that the joined path lexically remains under the corpus root by checking string prefix membership. However, this check is performed before symlink resolution. An attacker who can create a symlink at a path inside the corpus root (e.g., `/corpus/link` → `/etc/`) can then request access to `link/sensitive_file`, which passes lexical validation but resolves to a file outside the intended boundary after symlink expansion. The precondition is that the attacker can place files or symlinks in the corpus directory (e.g., via an extracted dataset, untrusted package, or compromised upload). The fix in version 3.9.4 resolves symlinks before boundary validation using os.path.realpath().
Affected products
- NLTK Project NLTK <= 3.9.3
Timeline
- 2026-08-07: disclosed
- 2026-09-08: advisory
- 2026-09-08: patched: Version 3.9.4 released