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.
nltk.downloader.Downloader.download, nltk.downloader.Downloader.incr_download3.9.4 and current source v3.10.0-rc2 both reproduced for the extraction-stage overwrite.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.
Preconditions
Steps
Downloader.download() package install whose extracted member lands on the hardlink path.Minimal reproducible excerpt
extract_hardlink_before ORIGINAL
extract_hardlink_after PWNED
extract_hardlink_status installed
A shared or attacker-influenced downloader directory can be turned into an overwrite primitive against same-filesystem files outside the intended install root.
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.
{
"cwe_ids": [
"CWE-59",
"CWE-61",
"CWE-73"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-02T14:35:41Z",
"nvd_published_at": null,
"severity": "MODERATE"
}