CVE-2026-12259: NLTK: unverified downloads allow malicious data swap

GHSA-5wp5-5229-5g6q MEDIUM
Published September 8, 2026
CISO Take

NLTK's package downloader fetches tokenizer models and corpora over HTTP but never verifies a SHA-256 checksum after the file lands on disk and before it's unzipped, so anything that can intercept the download or win a race on a shared filesystem can substitute its own payload. This matters because NLTK sits underneath 15,633 downstream packages, and tokenizer data such as punkt_tab is routinely pickled — meaning a swapped file isn't just corrupted data but a potential code-execution vector once it's loaded. There is no evidence of active exploitation (not in CISA KEV, no public PoC or Nuclei template) and the EPSS score of 0.001 reflects genuinely low real-world exploitation likelihood, since the attack requires either a MITM position, DNS poisoning, or local race-condition access (CVSS AC:H, UI:R). Upgrade to nltk 3.9.3, which the maintainers patched via GHSA-5wp5-5229-5g6q; until then, force HTTPS mirrors, avoid running `nltk.download()` on untrusted or shared multi-tenant hosts, and audit any environment where NLTK data was fetched over plain HTTP for unexpected pickle files in `nltk_data/`.

Sources: NVD GitHub Advisory OpenSSF ATLAS EPSS VulnCheck

What is the risk?

Medium severity (CVSS 5.3, AC:H/UI:R) reflects a real but narrow exploitation window: the attacker needs network position (MITM/DNS poisoning) or local filesystem race-condition access, plus some form of user interaction (triggering a download). There's no known public exploit, no Nuclei template, and it isn't in CISA KEV, and EPSS (0.001) confirms it's not being opportunistically targeted in the wild today. The risk is elevated by scale (15,633 dependents) and by the specific nature of what's downloaded — pickled tokenizer/model artifacts that are trusted and loaded without further validation downstream. This is a supply-chain integrity gap rather than an actively weaponized vulnerability; prioritize patching over emergency response.

How does the attack unfold?

Initial Access
Attacker gains a MITM position via network interception or DNS poisoning during NLTK's HTTP-based package download, or wins a race on a shared filesystem between os.replace() and extraction.
AML.T0010.001
Malicious Package Delivery
Attacker substitutes the legitimate NLTK package zip (e.g., punkt_tab tokenizer) with a crafted one containing attacker-controlled content, since no checksum is validated after download.
AML.T0011.001
Silent Installation
NLTK extracts and installs the unverified file into the user's nltk_data directory, trusting it as if it were the authentic package.
AML.T0018.002
Impact
The tampered tokenizer/model data is loaded by downstream NLP or RAG pipelines, potentially executing embedded malicious code or corrupting pipeline behavior.
AML.T0076

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Tokenizers pip <= 3.9.2 3.9.3
11.0K OpenSSF 5.8 15.8K dependents Pushed 8d ago 75% patched ~0d to patch Full package profile →

Do you use Tokenizers? You're affected.

How severe is it?

CVSS 3.1
5.3 / 10
EPSS
0.1%
chance of exploitation in 30 days
Higher than 1% of all CVEs
Exploitation Status
No known exploitation
Sophistication
Moderate

What is the attack surface?

AV AC PR UI S C I A
AV Network
AC High
PR None
UI Required
S Unchanged
C None
I High
A None

What should I do?

1 step
  1. 1) Upgrade to nltk >= 3.9.3, which is expected to add post-download checksum verification per the linked advisory and PR #3449. 2) Until patched, force NLTK to use HTTPS-only mirrors and avoid networks where MITM is plausible (public Wi-Fi, untrusted proxies). 3) In CI/CD and shared environments, pre-bake nltk_data into a trusted base image or artifact rather than downloading at build/runtime, eliminating the download-time attack window entirely. 4) On shared filesystems, restrict write permissions on the NLTK data directory to prevent the race-condition variant. 5) Detection: audit nltk_data/ directories for files with hashes that don't match the official NLTK package index, and monitor for unexpected outbound HTTP (not HTTPS) requests to nltk.org/nltk_data mirrors from build and inference hosts.

What does CISA's SSVC say?

Decision Track
Exploitation none
Automatable No
Technical Impact partial

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity
ISO 42001
A.6.2.3 - Third-party and supplier relationships
NIST AI RMF
GOVERN 6.1 - Third-party AI risk management
OWASP LLM Top 10
LLM05:2025 - Supply Chain Vulnerabilities

Frequently Asked Questions

What is CVE-2026-12259?

NLTK's package downloader fetches tokenizer models and corpora over HTTP but never verifies a SHA-256 checksum after the file lands on disk and before it's unzipped, so anything that can intercept the download or win a race on a shared filesystem can substitute its own payload. This matters because NLTK sits underneath 15,633 downstream packages, and tokenizer data such as punkt_tab is routinely pickled — meaning a swapped file isn't just corrupted data but a potential code-execution vector once it's loaded. There is no evidence of active exploitation (not in CISA KEV, no public PoC or Nuclei template) and the EPSS score of 0.001 reflects genuinely low real-world exploitation likelihood, since the attack requires either a MITM position, DNS poisoning, or local race-condition access (CVSS AC:H, UI:R). Upgrade to nltk 3.9.3, which the maintainers patched via GHSA-5wp5-5229-5g6q; until then, force HTTPS mirrors, avoid running `nltk.download()` on untrusted or shared multi-tenant hosts, and audit any environment where NLTK data was fetched over plain HTTP for unexpected pickle files in `nltk_data/`.

Is CVE-2026-12259 actively exploited?

No confirmed active exploitation of CVE-2026-12259 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-12259?

1) Upgrade to nltk >= 3.9.3, which is expected to add post-download checksum verification per the linked advisory and PR #3449. 2) Until patched, force NLTK to use HTTPS-only mirrors and avoid networks where MITM is plausible (public Wi-Fi, untrusted proxies). 3) In CI/CD and shared environments, pre-bake `nltk_data` into a trusted base image or artifact rather than downloading at build/runtime, eliminating the download-time attack window entirely. 4) On shared filesystems, restrict write permissions on the NLTK data directory to prevent the race-condition variant. 5) Detection: audit `nltk_data/` directories for files with hashes that don't match the official NLTK package index, and monitor for unexpected outbound HTTP (not HTTPS) requests to nltk.org/nltk_data mirrors from build and inference hosts.

What systems are affected by CVE-2026-12259?

This vulnerability affects the following AI/ML architecture patterns: RAG pipelines, training pipelines, NLP preprocessing pipelines, CI/CD build pipelines.

What is the CVSS score for CVE-2026-12259?

CVE-2026-12259 has a CVSS v3.1 base score of 5.3 (MEDIUM). The EPSS exploitation probability is 0.10%.

What is the AI security impact?

Affected AI Architectures

RAG pipelinestraining pipelinesNLP preprocessing pipelinesCI/CD build pipelines

MITRE ATLAS Techniques

AML.T0010 AI Supply Chain Compromise
AML.T0010.001 AI Software
AML.T0011.001 Malicious Package
AML.T0018.002 Embed Malware

Compliance Controls Affected

EU AI Act: Article 15
ISO 42001: A.6.2.3
NIST AI RMF: GOVERN 6.1
OWASP LLM Top 10: LLM05:2025

What are the technical details?

Original Advisory

NLTK's package downloader in nltk/downloader.py does not verify file integrity after download and before extraction. The download flow at lines 789-825: 1. File is downloaded to a temp path via HTTP 2. os.replace(tmp_filepath, filepath) moves it to the final location (line 799) 3. Extraction begins via _unzip_iter() (line 825) Between steps 2 and 3, there is no SHA-256 verification. The checksum logic exists in _pkg_status() (lines 982-1015) but it is only used BEFORE download as a status check ("is this package already installed and up-to-date?"). It is never called after download to verify the file that was actually received. Attack vectors: 1. MITM during HTTP download (NLTK downloads from http:// by default on some mirrors) 2. Race condition on shared filesystems (attacker replaces file between os.replace and _unzip_iter) 3. DNS poisoning redirecting to attacker-controlled server PoC: ```python import nltk import unittest.mock import zipfile import io import os # Create a malicious zip that will be "downloaded" malicious_zip = io.BytesIO() with zipfile.ZipFile(malicious_zip, 'w') as zf: zf.writestr('punkt_tab/tokenizers/punkt_tab/english.pickle', b'MALICIOUS PAYLOAD - attacker controlled content') # Patch urllib to return our malicious zip with unittest.mock.patch('urllib.request.urlopen') as mock_urlopen: mock_response = unittest.mock.MagicMock() mock_response.read.return_value = malicious_zip.getvalue() mock_response.headers = {'Content-Length': str(len(malicious_zip.getvalue()))} mock_urlopen.return_value = mock_response # Download proceeds, no integrity check catches the swap # nltk.download('punkt_tab') # Would install attacker payload ``` This is distinct from CVE-2024-39705 (pickle deserialization via download) and CVE-2025-14009 (zip-slip path traversal). Those address what happens AFTER extraction. This finding addresses the gap BEFORE extraction where integrity is never verified. Suggested fix: After os.replace() and before _unzip_iter(), compute SHA-256 of the final file and compare against the expected checksum from the package index. Reject and delete the file if the hash does not match.

Exploitation Scenario

An adversary positioned on a shared network (coffee shop Wi-Fi, compromised router, or a rogue AP near a corporate office) waits for a data scientist or CI job to run `nltk.download('punkt_tab')`. Because some NLTK mirrors serve over plain HTTP, the attacker intercepts the request via ARP spoofing or DNS poisoning and returns a crafted zip containing a malicious `english.pickle` in place of the legitimate tokenizer model. NLTK moves the file into place and extracts it without ever checking its hash against the expected value, so the swap is invisible to the victim. The next time the RAG or NLP pipeline loads that tokenizer, the pickle deserializes and the attacker's embedded payload executes with the privileges of the pipeline process — turning a routine dependency fetch into remote code execution deep inside the victim's data pipeline.

Weaknesses (CWE)

CWE-494 — Download of Code Without Integrity Check: The product downloads source code or an executable from a remote location and executes the code without sufficiently verifying the origin and integrity of the code.

  • [Implementation] Perform proper forward and reverse DNS lookups to detect DNS spoofing.
  • [Architecture and Design, Operation] Encrypt the code with a reliable encryption scheme before transmitting. This will only be a partial solution, since it will not detect DNS spoofing and it will not prevent your code from being modified on the hosting site.

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N

Timeline

Published
September 8, 2026
Last Modified
September 8, 2026
First Seen
September 8, 2026

Related Vulnerabilities