CVE-2026-78682: NLTK: SSRF bypass via proxy-handler downgrade

GHSA-6ww7-3frv-cqxh HIGH PoC AVAILABLE CISA: TRACK*
Published September 8, 2026
CISO Take

NLTK's pathsec module validates hostnames before fetching URLs, but when an HTTP proxy is configured, the library silently routes the request through the proxy's handlers instead of the pinned, validated socket path — letting a proxied request reach internal-only services or forge a downloader index while the validated hostname check reports success. The blast radius looks contained on paper (2 tracked downstream dependents, EPSS 0.00253, no CISA KEV listing, no public exploit or Nuclei template), but nltk is a foundational NLP dependency embedded deep in text-preprocessing and RAG-adjacent pipelines, and any environment that enforces an egress proxy — common in regulated enterprises — is exactly the setup this bug reactivates. Exploitation requires an adversary with influence over the proxy path (compromised corporate proxy, malicious insider, or an SSRF chained from another service), which raises the bar from trivial but does not eliminate real risk in proxy-mandated networks. Patch to nltk 3.10.3, which fails closed on proxied fetches by default; until then, do not set `NLTK_ALLOW_PROXIED_URLOPEN=1` and audit any service that calls `nltk.data.load()` or `Downloader.download()` from inside a proxied network for unexpected corpus/index sources.

Sources: NVD GitHub Advisory EPSS

What is the risk?

High severity per the advisory but tempered by real-world exploitability constraints: the attacker needs some control over or visibility into the victim's outbound proxy path, not just network reachability to the target service. There is no CISA KEV listing, no public exploit code, and no Nuclei template, and EPSS scores this at 0.00253 (a low absolute exploitation probability). However, the affected code paths (`pathsec.urlopen`, `nltk.data.load`, `Downloader.index`/`download`) are core to how nltk fetches remote corpora and packages, so any deployment relying on nltk's SSRF protections while running behind a corporate/CI proxy is exposed until patched. Package risk score is reported as 0/100 and downstream dependents as only 2, suggesting limited direct blast radius today, but nltk's ubiquity in NLP tooling means indirect exposure (via other packages bundling it) is likely undercounted.

How does the attack unfold?

Initial Access
Attacker gains control over or visibility into the proxy path used by an nltk-based service running in a proxied network environment.
Proxy Redirection
The attacker configures the proxy to redirect a validated public URL to an internal loopback service or a forged downloader index, bypassing nltk's pinned-IP SSRF protection.
AML.T0049
Data Exfiltration / Malicious Content Install
nltk returns internal-only secret content as if it were the validated public resource, or installs an attacker-chosen ZIP as trusted corpus/package data.
AML.T0010.002

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Cline pip <= 3.10.2 3.10.3
67.9K 2 dependents Pushed 7d ago 57% patched ~0d to patch Full package profile →

Do you use Cline? You're affected.

How severe is it?

CVSS 3.1
N/A
EPSS
0.3%
chance of exploitation in 30 days
Higher than 17% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Moderate
Exploitation Confidence
medium
CISA SSVC: Public PoC
Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What should I do?

1 step
  1. 1) Upgrade to nltk 3.10.3 or later, which fails closed on proxied fetches under ENFORCE and requires explicit opt-in (NLTK_ALLOW_PROXIED_URLOPEN=1 or nltk.pathsec.ALLOW_PROXIED_FETCH=True) to restore proxied behavior. 2) If you cannot upgrade immediately, avoid running nltk data-fetching code (nltk.data.load, Downloader.index/download) in any environment with http_proxy/https_proxy set, or block those variables for the process. 3) Only enable the opt-in flag if you fully trust your proxy's egress control and have validated it cannot be pointed at internal-only hosts. 4) Detection: audit environment variables in containers/CI runners that invoke nltk downloads for proxy configuration, monitor proxy logs for nltk-driven requests resolving to loopback/internal ranges, and alert on unexpected corpus checksums or ZIP contents from nltk_data installs.

What does CISA's SSVC say?

Decision Track*
Exploitation poc
Automatable Yes
Technical Impact partial

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

How is it classified?

Data Leakage Supply Chain Framework Training Data AML.T0010.002 AML.T0025

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Article 10 - Data and data governance
NIST AI RMF
MANAGE 4.1 - Risk monitoring for third-party AI resources
OWASP LLM Top 10
LLM05 - Supply Chain Vulnerabilities

Frequently Asked Questions

What is CVE-2026-78682?

NLTK's pathsec module validates hostnames before fetching URLs, but when an HTTP proxy is configured, the library silently routes the request through the proxy's handlers instead of the pinned, validated socket path — letting a proxied request reach internal-only services or forge a downloader index while the validated hostname check reports success. The blast radius looks contained on paper (2 tracked downstream dependents, EPSS 0.00253, no CISA KEV listing, no public exploit or Nuclei template), but nltk is a foundational NLP dependency embedded deep in text-preprocessing and RAG-adjacent pipelines, and any environment that enforces an egress proxy — common in regulated enterprises — is exactly the setup this bug reactivates. Exploitation requires an adversary with influence over the proxy path (compromised corporate proxy, malicious insider, or an SSRF chained from another service), which raises the bar from trivial but does not eliminate real risk in proxy-mandated networks. Patch to nltk 3.10.3, which fails closed on proxied fetches by default; until then, do not set `NLTK_ALLOW_PROXIED_URLOPEN=1` and audit any service that calls `nltk.data.load()` or `Downloader.download()` from inside a proxied network for unexpected corpus/index sources.

Is CVE-2026-78682 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2026-78682, increasing the risk of exploitation.

How to fix CVE-2026-78682?

1) Upgrade to nltk 3.10.3 or later, which fails closed on proxied fetches under `ENFORCE` and requires explicit opt-in (`NLTK_ALLOW_PROXIED_URLOPEN=1` or `nltk.pathsec.ALLOW_PROXIED_FETCH=True`) to restore proxied behavior. 2) If you cannot upgrade immediately, avoid running nltk data-fetching code (`nltk.data.load`, `Downloader.index`/`download`) in any environment with `http_proxy`/`https_proxy` set, or block those variables for the process. 3) Only enable the opt-in flag if you fully trust your proxy's egress control and have validated it cannot be pointed at internal-only hosts. 4) Detection: audit environment variables in containers/CI runners that invoke nltk downloads for proxy configuration, monitor proxy logs for nltk-driven requests resolving to loopback/internal ranges, and alert on unexpected corpus checksums or ZIP contents from `nltk_data` installs.

What systems are affected by CVE-2026-78682?

This vulnerability affects the following AI/ML architecture patterns: training pipelines, RAG pipelines, agent frameworks.

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

No CVSS score has been assigned yet.

What is the AI security impact?

Affected AI Architectures

training pipelinesRAG pipelinesagent frameworks

MITRE ATLAS Techniques

AML.T0010.002 Data
AML.T0025 Exfiltration via Cyber Means

Compliance Controls Affected

EU AI Act: Article 10
NIST AI RMF: MANAGE 4.1
OWASP LLM Top 10: LLM05

What are the technical details?

Original Advisory

### Summary Current NLTK source reopens SSRF in proxied environments. `pathsec.urlopen()` validates the requested hostname locally, but once proxy inheritance is enabled the real fetch is performed by the proxy rather than by the validated direct-connect socket path. ### Details - **Vulnerability type:** Server-side request forgery - **Affected component:** `nltk.pathsec.urlopen`, `nltk.data.load`, `nltk.downloader.Downloader.index`, `nltk.downloader.Downloader.download` - **Affected versions:** Current source `v3.10.0-rc2`; published `3.9.4` was a negative control and did not reproduce. - **Patched versions:** Not yet patched - **Root cause:** Proxy-handler inheritance disables `_SafeHTTPHandler` and `_SafeHTTPSHandler`, so the validated hostname no longer matches the actual egress destination. The hardened direct path pins the validated numeric destination IP before opening the socket. The proxied branch instead copies `ProxyHandler` instances from the global opener, marks the request as proxied, and skips the pinned handlers. I confirmed that a validated public URL can be fetched from a loopback-only internal service through the proxy path via `pathsec.urlopen()`, `nltk.data.load()`, `Downloader.index()`, and `Downloader.download()`. ### PoC **Preconditions** - The runtime has an HTTP proxy configured and the caller relies on `pathsec` to keep network fetches SSRF-safe. **Steps** 1. Start a loopback-only HTTP server that serves secret text, a valid downloader index, and a ZIP payload. 2. Configure a proxy that forwards a validated public URL to that internal loopback service. 3. Call `pathsec.urlopen()` or `nltk.data.load()` on the public URL and observe the internal response is returned. 4. Instantiate `Downloader(server_index_url=...)`, call `index()` and `download()`, and observe internal-only content is parsed and installed. **Minimal reproducible excerpt** ```text {'urlopen': 'PROXY_TEXT_SECRET', 'data_load': 'PROXY_TEXT_SECRET', 'downloaded_file': 'INTERNAL_ZIP_SECRET'} ``` ### Impact Consumers that trust `pathsec` as an SSRF barrier in proxied environments can be made to read internal-only HTTP resources, load forged downloader indexes, and install attacker-chosen package content fetched from the proxy's network view. ### Remediation Preserve destination validation for the actual proxy egress target or fail closed when the request would otherwise downgrade into an unpinned proxied path. Add regression tests across `pathsec.urlopen`, `nltk.data.load`, and downloader fetches with a configured proxy. ### References - https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/pathsec.py#L468-L518 - https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/data.py#L1247-L1283 - https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/downloader.py#L875-L889 - https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/downloader.py#L1220-L1226 - https://github.com/nltk/nltk/blob/3.9.4/nltk/pathsec.py#L245-L250 --- ## Fix + attack demonstration (verified) NLTK cannot pin the egress through a proxy, so it stops pretending to: under `ENFORCE` a proxied fetch is **refused** rather than performed unvalidated. Operators who trust their proxy opt back in with `NLTK_ALLOW_PROXIED_URLOPEN=1` or `nltk.pathsec.ALLOW_PROXIED_FETCH=True`; under `ENFORCE=False` the refusal degrades to a warning. This closes the **whole class** (environment proxies and explicit `ProxyHandler` alike), because NLTK declines any fetch whose egress it cannot validate. ## Attack demonstration (reproduced; captured output) A loopback HTTP server stands in for the internal target; `http_proxy` points at it; NLTK is asked for a **public** IP URL. **Before the fix** — the internal secret is exfiltrated through the proxy: ``` validate_network_url(public): PASSED *** BYPASS: pathsec.urlopen returned INTERNAL content via proxy: 'INTERNAL_ONLY_SECRET' ``` **After the fix** — five scenarios, isolated subprocesses: | Scenario | Result | |---|---| | proxied (env) + ENFORCE | `PermissionError` — **blocked** | | proxied + opt-in | returns secret — escape hatch works | | explicit `ProxyHandler` (not env) + ENFORCE | `PermissionError` — **blocked** (whole class) | | no proxy (direct) | internal IP still refused — pinning intact | | proxied + `ENFORCE=False` | returns secret **+ warns** | ## Tests `nltk/test/unit/test_pathsec.py`: 64 passed. Added an end-to-end regression (`test_proxied_fetch_does_not_reach_internal_target`) plus `test_env_proxy_fails_closed_under_enforce`; the prior `test_env_proxy_skips_pinning_handlers` (which encoded the vulnerable path) is re-expressed as the opt-in case. Existing direct-path DNS-rebinding and IP-policy tests unchanged and passing. pre-commit (isort/black/ruff) clean. ## Note The upfront `validate_network_url()` and the direct-path IP pinning (from the earlier DNS-rebinding fixes, CVE-2026-54296 / GHSA-qvv7) are unchanged — this only closes the proxied downgrade they didn't cover.

Exploitation Scenario

An AI/NLP service runs inside a corporate network that enforces an outbound HTTP proxy for compliance/egress-control reasons. An attacker who has compromised that proxy (or is an insider with proxy access) configures it to redirect a validated, public-looking download URL to an internal loopback service instead. When the nltk-based service calls `Downloader.download()` to fetch a 'trusted' corpus or model resource, the proxy transparently substitutes internal content: a forged downloader index pointing to attacker-controlled ZIP files. Because nltk's `_SafeHTTPHandler`/`_SafeHTTPSHandler` pinning is silently bypassed once proxy inheritance kicks in, the service installs and later loads the attacker's ZIP as if it were the legitimate resource — enabling either exfiltration of internal-only data (secrets served by the loopback host) or a supply-chain-style substitution of trusted linguistic data with attacker-controlled content.

Weaknesses (CWE)

CWE-441 — Unintended Proxy or Intermediary ('Confused Deputy'): The product receives a request, message, or directive from an upstream component, but the product does not sufficiently preserve the original source of the request before forwarding the request to an external actor that is outside of the product's control sphere. This causes the product to appear to be the source of the request, leading it to act as a proxy or other intermediary between the upstream component and the external actor.

  • [Architecture and Design] Enforce the use of strong mutual authentication mechanism between the two parties.
  • [Architecture and Design] Whenever a product is an intermediary or proxy for transactions between two other components, the proxy core should not drop the identity of the initiator of the transaction. The immutability of the identity of the initiator must be maintained and should be forwarded all the way to the target.

Source: MITRE CWE corpus.

Timeline

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

Related Vulnerabilities