GHSA-f794-5jv7-7672: High severity pip/nltk vulnerability
Summary
NLTK's downloader now blocks symlink escapes during ZIP extraction, but it still treats pre-existing hardlinks inside the install tree as ordinary in-root files. A normal package install can therefore overwrite an outside-root inode through that hardlink.
Details
- Vulnerability type: Filesystem containment bypass - Affected component: nltk.downloader.Downloader.download, nltk.downloader.Downloader.incrdownload - Affected versions: Published 3.9.4 and current source v3.10.0-rc2 both reproduced for the extraction-stage overwrite. - Patched versions: 3.10.3 - Root cause: The downloader validates traversal and symlink conditions but does not reject pre-existing hardlink aliases inside the install tree.
The install flow correctly rejects a pre-existing symlink at an extraction target, yet it accepts a pre-existing hardlink at the same path. When the package is installed, extracted member data is written through the hardlink and mutates the outside inode.
PoC
Preconditions - The attacker can plant files inside a writable shared downloader root on the same filesystem as the target file.
Steps 1. Prepare a downloader root and create a hardlink inside it that points to an outside target file. 2. Confirm a symlink at the same path is rejected as a negative control. 3. Run a normal Downloader.download() package install whose extracted member lands on the hardlink path. 4. Observe the outside target file is overwritten while the downloader still reports the package as installed.
Minimal reproducible excerpt
text extracthardlinkbefore ORIGINAL extracthardlinkafter PWNED extracthardlinkstatus installed
Impact
A shared or attacker-influenced downloader directory can be turned into an overwrite primitive against same-filesystem files outside the intended install root.
Remediation
Treat pre-existing hardlinks as unsafe in extraction targets, verify that each write path stays within the intended install tree at the inode level, and add regression tests that pair hardlinks with existing symlink controls.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/nltkto a version that resolves this vulnerability.Fixed in 3.10.3 - Upgrade
Upgrade
nltk.downloader.Downloaderto a version that resolves this vulnerability.Fixed in 3.10.3 - Configuration
In the install/extraction flow, treat pre-existing hardlinks at extraction targets as unsafe (i.e., reject/block them), in addition to the existing rejection of symlink escapes. Also verify each write path stays within the intended install tree at the inode level during extraction.
NLTK downloader ZIP extraction pre-existing hardlinks handling at extraction targets = block (treat as unsafe)
Event History
Frequently Asked Questions
Which deployments are realistically exposed?
Deployments using an NLTK downloader root that is writable by multiple parties are exposed if an attacker can create files in that root. The downloader root must also be on the same filesystem as the outside file the attacker intends to modify.
What does an attacker need to exploit this issue?
The attacker needs the ability to plant a pre-existing hardlink inside the writable downloader install tree, pointing to an outside-root inode. A subsequent normal package installation causes extracted data to be written through that hardlink.
Does existing symlink protection prevent this attack?
No. The install flow rejects a pre-existing symlink at an extraction target, but it accepts a pre-existing hardlink at that path, allowing the outside inode to be overwritten.
Which versions should be updated?
The extraction-stage overwrite was reproduced in published version 3.9.4 and source version v3.10.0-rc2. Version 3.10.3 is listed as patched.