High

NLTK: pathsec SSRF protection can be bypassed when a proxy is configured

  • Disclosed: 25.08.2026
  • Updated: 11.10.2026 15:17

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

{'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


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.

Affected software

Click a technology to see all vulnerabilities affecting it.

PlatformPackageVulnerable versionsFixed in
Python (PyPI) nltk < 3.10.3 3.10.3

References

CVSS score -
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Weakness (CWE)
CWE-441, CWE-918
Platform
Python (PyPI)
Package
nltk
Disclosed
25.08.2026
Updated
11.10.2026 15:17

Sources and licenses

OSV / GitHub Advisory Database - PYSEC-2026-3733 - PyPA Advisory Database; CC BY 4.0

OSV / GitHub Advisory Database - GHSA-6ww7-3frv-cqxh - CC BY 4.0

Vulnerability history: nltk

All published vulnerabilities of this package (Python (PyPI)), newest first. Shows whether this is a one-off slip or a package that needs watching.

All (52) in the archive
Total entries
52
First → latest
08.2019 09.2026
Without a fix
6
Exploited in attacks
0

Severity breakdown

  • Critical 5
  • High 32
  • Medium 13
  • Low 2

Disclosures per year

  1. 2019: 1
  2. 2020: 0
  3. 2021: 2
  4. 2022: 1
  5. 2023: 0
  6. 2024: 1
  7. 2025: 0
  8. 2026: 47
Severity:
  1. High CVE-2026-79674 < 3.10.3 3.10.3
  2. NLTK: pathsec SSRF protection can be bypassed when a proxy is configured this entry
    High CVE-2026-78682 < 3.10.3 3.10.3
  3. High · 8.8 CVE-2026-71513 >= 3.10.0, < 3.10.3 3.10.3
  4. High · 5.9 CVE-2026-62385 < 3.10.0 3.10.0
Show more (17) Showing 20 of 37

Know which vulnerabilities affect your application

With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.

Connect your application
DockRay newsletter

Application security in your inbox

Important vulnerabilities, actionable guidance and practical advice for your applications. Choose your technologies and follow what matters to your project.

  • A daily digest of new vulnerabilities, critical ones included.
  • Notifications about important updates.
  • Practical advice on application security and monitoring.

Leave empty to receive updates for every technology.

Free to subscribe. Unsubscribe with one click in any email.