CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-12259

CVE-2026-12259: Improper Integrity Verification (Extract-Before-Verify) in NLTK Downloader

Alon Barad
Alon Barad
Software Engineer

Sep 8, 2026·7 min read·5 visits

Executive Summary (TL;DR)

NLTK's downloader extracts remote packages to the local filesystem before verifying their cryptographic hash, allowing man-in-the-middle or mirror-hijacking attackers to write arbitrary files or execute untrusted code.

An improper integrity verification vulnerability exists in the Natural Language Toolkit (NLTK) library up to and including version 3.9.4. The library's download utility writes remote ZIP packages directly to disk and extracts their contents onto the filesystem before executing cryptographic checksum validation. An attacker capable of intercepting or manipulating the download stream can exploit this behavior to perform arbitrary file writes, directory traversal, or execute untrusted serialized content.

Vulnerability Overview

The Natural Language Toolkit (NLTK) is a widely used Python platform for processing human language data, providing interfaces to over fifty corpora and lexical resources. To manage these resources, NLTK includes a programmatic downloader utility designed to retrieve compressed archives of models and datasets from remote mirrors. This capability exposes an attack surface that is heavily reliant on the integrity of the downloaded archives before they are processed by the host system.

CVE-2026-12259 represents an improper integrity verification vulnerability within this downloader framework, specifically categorized under CWE-494. The vulnerability arises due to an insecure sequence of execution in the archive-handling logic. The application retrieves remote ZIP packages and decompresses them onto the local filesystem before executing any cryptographic verification steps.

This "extract-before-verify" design pattern permits an adversary who can manipulate the data stream to inject and unpack malicious file hierarchies. Because validation is decoupled from the extraction lifecycle, arbitrary payload files are successfully positioned on the disk before the application discovers that the archive is modified. This sequence can lead to directory traversal, overwrite of critical configuration files, or local execution of malicious serialized objects.

Technical Root Cause Analysis

The core of the vulnerability lies in the implementation of the nltk.downloader.Downloader._download_package() method within nltk/downloader.py. The downloader checks the installation status of a package prior to executing a download request. It utilizes the _pkg_status() helper function to verify if the file exists locally and if its checksum is valid. This mechanism acts solely as an installation and update caching check.

Once the downloader determines that a package needs to be updated or retrieved, it enters a standard write sequence. The function establishes an HTTP connection to the remote server via Python's urllib.request.urlopen() and sequentially streams the remote bytes in blocks of 16 kilobytes directly into a target file on disk.

Immediately after completing the file write, the control flow evaluates if the package name ends with .zip and if extraction is requested. If these conditions are met, the method invokes the _unzip_iter() function. This decompression utility reads the newly written, unverified ZIP archive and extracts all contents into the designated local directory. Crucially, the integrity check is omitted during this transition phase. The cryptographic validation logic is never executed on the freshly written bytes prior to unpacking, exposing the local file system to untrusted input.

Code-Level Flow & Patch Analysis

To understand the structural failure, we analyze the implementation flow in nltk/downloader.py. The downloader retrieves the archive byte streams and processes them directly through file-writing loops. The vulnerable execution structure is shown below:

# Vulnerable downloader pipeline
infile = urlopen(info.url)
with open(filepath, "wb") as outfile:
    for block in itertools.count():
        s = infile.read(1024 * 16)
        outfile.write(s)
        if not s:
            break
infile.close()
 
# Vulnerable Sequence: Immediate unzip before verifying integrity
if info.filename.endswith(".zip"):
    zipdir = os.path.join(download_dir, info.subdir)
    if info.unzip:
        # Extraction occurs on unverified file data
        for msg in _unzip_iter(filepath, zipdir, verbose=False):
            yield msg

A partial fix was introduced in GitHub pull request #3449. The development team modified the internal _pkg_status() method to transition the hashing mechanism from MD5 to SHA-256. This alteration addressed cryptographic weaknesses associated with hash collisions in local environment validation, but it failed to correct the sequencing defect.

# Patch in commit 0e26734a61094b628d93e26dc18dd7302567ac46
def _pkg_status(self, info, filepath):
    if not os.path.exists(filepath):
        return self.NOT_INSTALLED
    # Swapped MD5 comparison for SHA-256
    # if md5_hexdigest(filepath) != info.checksum:
    if sha256_hexdigest(filepath) != info.sha256_checksum:
        return self.STALE
    return self.INSTALLED

Exploitation Mechanics & Threat Scenarios

Exploitation of CVE-2026-12259 relies on an attacker intercepting or redirecting the downloader's network traffic to substitute the legitimate ZIP archive with a malicious alternative. Because the user must initiate the package download, the vulnerability is classified as requiring user interaction. However, in automated deployment scripts, server initialization routines, or cloud container bootstrapping, this interaction occurs programmatically without manual operator oversight.

If an attacker controls a local DNS resolver, compromises a custom package mirror, or performs a Man-in-the-Middle (MITM) attack over unencrypted channels, they can redirect requests for NLTK assets. When the target environment requests a corpus, the attacker's server responds with a modified ZIP archive. This archive contains files crafted with directory traversal sequences (e.g., ../../) or malicious Python serialization formats such as PyTorch model weights or pickle files.

During the download, NLTK saves the payload and immediately hands it to the extraction process. The zip utility processes the compressed data, unpacking the malicious files directly onto the system. If directory traversal sequences are processed, the application may overwrite executable scripts or configuration files in adjacent directories. If a malicious pickle file or serialized model is extracted, subsequent application attempts to load the dataset will result in arbitrary code execution in the context of the running Python process.

Assessment of Patch Adequacy

A critical analysis of the patch applied in commit 0e26734a61094b628d93e26dc18dd7302567ac46 reveals that the remediation is fundamentally incomplete. Replacing MD5 with SHA-256 within the _pkg_status() function is a positive cryptographic upgrade. However, it does not alter the sequential vulnerability present in the download execution path.

Because _download_package() does not call _pkg_status() or perform any checksum calculation after writing the remote bytes and before invoking _unzip_iter(), the system remains exposed. The file is still extracted to disk immediately upon download. The verification check is only triggered in subsequent execution loops or when the downloader is re-initialized, meaning the malicious payload is already successfully unzipped onto the local storage before any validation occurs.

For a remediation to be mathematically and operationally secure, the application must isolate the newly written binary payload. A cryptographic hash of the temporary file must be calculated in-memory immediately after the write loop finishes. This hash must be compared to the trusted index hash, and only upon a successful match should the file be passed to the extraction utility. If the hash comparison fails, the temporary file must be safely deleted, and an execution error must be raised.

Remediation & Detection Strategies

Securing environments running vulnerable versions of NLTK requires a combination of patching, configuration hardening, and behavioral monitoring. Organizations must verify that their python environments are updated to a release of NLTK that implements a complete download-then-verify sequence. In systems where upgrading the library is blocked by compatibility constraints, alternative workarounds must be applied.

One highly effective mitigation is to disable dynamic package retrieval within production environments. Security teams should pre-provision the necessary NLTK corpora during the container build or system deployment phase. By statically downloading, cryptographically verifying, and locking the nltk_data directory within a read-only filesystem, the dynamic execution of nltk.download() is rendered unnecessary and can be entirely blocked.

From a detection perspective, network monitoring tools should be configured to detect and flag non-SSL HTTP connections initiated by Python user-agents toward external repositories. Additionally, host-based intrusion detection systems (HIDS) should monitor the directories designated for NLTK datasets. Any anomalous write activity, particularly the creation of files with directory traversal characters or execution scripts within database paths, should trigger high-priority security alerts.

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N
EPSS Probability
0.10%
Top 100% most exploited

Affected Systems

Python environments running NLTK installations

Affected Versions Detail

Product
Affected Versions
Fixed Version
nltk
NLTK
<= 3.9.43.9.5
AttributeDetail
CWE IDCWE-494
Attack VectorNetwork
CVSS5.3
EPSS Score0.001
ImpactHigh Integrity Impact
Exploit StatusProof-of-Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1557Man-in-the-Middle
Credential Access
T1195.001Supply Chain Compromise: Compromise Software Dependencies and Development Tools
Initial Access
CWE-494
Download of Code Without Integrity Check

The product downloads source code, an executable, or a configuration file from a source, but does not sufficiently verify that the code was not modified since it was created.

References & Sources

  • [1]https://www.cve.org/CVERecord?id=CVE-2026-12259
  • [2]https://huntr.com/bounties/659ccf6d-12d4-4d4a-84c0-078633c35a5d
  • [3]https://github.com/nltk/nltk/pull/3449
  • [4]https://github.com/nltk/nltk/commit/0e26734a61094b628d93e26dc18dd7302567ac46
  • [5]https://github.com/nltk/nltk/issues/3407
  • [6]https://github.com/nltk/nltk/releases/tag/3.9.3
  • [7]https://www.wiz.io/vulnerability-database/cve/cve-2026-12259

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•32 minutes ago•CVE-2026-78677
7.5

CVE-2026-78677: Path Traversal and Arbitrary File Write in GitPython

GitPython prior to version 3.1.59 contains a path traversal vulnerability via parameter injection. The clone denylist did not restrict the `--separate-git-dir` option, allowing attackers to write repository metadata to arbitrary system paths.

Alon Barad
Alon Barad
2 views•6 min read
•about 2 hours ago•CVE-2026-72925
6.1

CVE-2026-72925: Cross-Site Scripting via Improper JSON Escaping in SWC HTML Minifier

CVE-2026-72925 is a critical vulnerability in the SWC HTML minifier (@swc/html and swc_html_minifier) where safe Unicode-escaped characters in embedded JSON script tags are normalized into raw, unescaped characters during optimization, causing browser-side HTML injection and Cross-Site Scripting.

Amit Schendel
Amit Schendel
3 views•7 min read
•about 3 hours ago•CVE-2026-79674
8.8

CVE-2026-79674: Path Sandbox Bypass in NLTK CorpusReader Constructors

A critical logical flaw in the Natural Language Toolkit (NLTK) allows attackers to bypass the application-level directory sandbox. This vulnerability enables unauthenticated directory enumeration and arbitrary local file or SQLite database access.

Amit Schendel
Amit Schendel
4 views•6 min read
•3 days ago•CVE-2026-75856
9.2

CVE-2026-75856: Server-Side Request Forgery (SSRF) Bypass via DNS Resolution TOCTOU in CodeWhale

A critical Server-Side Request Forgery (SSRF) bypass vulnerability exists in CodeWhale before version 0.8.64 (and version 0.8.41 in the 0.8.x branch) due to a Time-of-Check to Time-of-Use (TOCTOU) bug in its DNS pre-flight validation mechanism. By returning a temporary resolution failure during validation and subsequently resolving to restricted IPs during HTTP execution, attackers can bypass security rules.

Amit Schendel
Amit Schendel
17 views•6 min read
•3 days ago•CVE-2026-75912
8.3

CVE-2026-75912: Argument Injection and Arbitrary File Disclosure in CodeWhale Git Tools

An argument injection vulnerability in CodeWhale (CVE-2026-75912 / GHSA-c6mw-8xh8-gpq6) allows unauthenticated remote attackers to execute arbitrary option commands on the git binary. By passing malicious command-line flags inside git_blame and git_show tool helper functions, an attacker can bypass typical access controls to read arbitrary local system files via the underlying git process.

Alon Barad
Alon Barad
15 views•5 min read
•3 days ago•CVE-2026-63735
8.6

CVE-2026-63735: Cross-Tenant Authorization Bypass in SurrealDB Custom API Routing Handler

SurrealDB prior to version 3.2.0 is vulnerable to an authorization bypass where authenticated users can invoke custom API endpoints belonging to other tenants. This cross-tenant data access occurs because the system fails to validate authorization scope boundaries against request-supplied namespace and database identifiers before executing scripts with elevated definer's rights.

Amit Schendel
Amit Schendel
13 views•6 min read