CVE-2026-97687
Executive Summary
CVE-2026-97687 is a TLS configuration isolation failure in the Python urllib3 HTTP client library, affecting versions from 1.26.0 through 2.7.x. When applications route traffic through an HTTPS proxy while applying target-server TLS settings (such as cert_reqs=CERT_NONE, ssl_context, or proxy_ssl_context), those settings can bleed into the proxy TLS handshake because the target-server TLS context is incorrectly shared with the proxy connection. This allows a network-positioned attacker to impersonate the HTTPS proxy without triggering certificate verification, then observe or modify forwarded traffic and potentially capture a target TLS client certificate. The issue is fixed in urllib3 2.8.0.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability class is improper certificate validation (CWE-295), arising from a failure to keep the TLS configuration of two distinct connections logically separate: the client-to-proxy connection and the client-to-target connection. In normal operation, an HTTPS proxy connection uses proxy_ssl_context and its associated settings (proxy_assert_hostname, proxy_assert_fingerprint), while the target-server TLS handshake uses ssl_context, cert_reqs, and verify_mode. The NVD description states that from version 1.26.0 until 2.8.0, these configuration paths "fail to remain separated because target-server TLS settings are incorrectly applied to the HTTPS proxy connection."
The trigger conditions described are: an application uses an HTTPS proxy and configures target-server TLS settings that must remain isolated from the proxy TLS handshake, including HTTPS forwarding with target-specific identity or credentials. The specific dangerous mutation is that "applying cert_reqs=CERT_NONE can overwrite proxy_ssl_context.verify_mode in place." Critically, this mutation persists because the underlying SSL context object is reused: later connections that reuse the same context "may connect to the HTTPS proxy without certificate verification."
The attack mechanism is that an adversary with a network position intercepts and impersonates the HTTPS proxy once the effective proxy policy accepts the attacker's certificate. Because verify_mode was mutated to CERT_NONE, no certificate validation occurs on the proxy leg. The impact is that the attacker can observe or modify traffic forwarded through the proxy, or receive a target TLS client certificate. Notably, the description clarifies that CONNECT tunneling still preserves the separate end-to-end target TLS connection — the compromise is scoped to the proxy leg and the metadata/credentials exposed through forwarding.
The attack surface is any Python application that (a) uses an HTTPS proxy, (b) configures target-server TLS settings intended to remain separate from proxy TLS, and (c) in the worst case sets cert_reqs=CERT_NONE (for example for test or legacy endpoints). Because the mutation is in-place and persistent, the exposure is not limited to the single misconfigured request; all subsequent connections reusing the same SSL context are affected. use_forwarding_for_https=True is explicitly named as one of the affected configuration paths, meaning HTTPS forwarding (not just CONNECT tunneling) is within scope.
No public proof-of-concept, exploit code, or Nuclei template is available. The preceding analysis is derived strictly from the NVD description.
Exploitation Scenarios
Reconnaissance / target identification. The attacker identifies a target application that reaches external services through an HTTPS proxy. Position awareness (network tap, hostile transit AS, compromised proxy infrastructure, or on-path MITM) is required. The attacker does not need a specific PoC; the vulnerability is a policy-isolation defect triggered by application configuration, not a remotely injectable input.
Triggering the flaw class. The target application — on its own, as part of legitimate configuration — sets target-server TLS parameters (e.g.,
cert_reqs=CERT_NONE, or anssl_context/verify_modevalue intended for the target server) while also using an HTTPS proxy. The library incorrectly applies the target-server TLS settings to the proxy connection. Wherecert_reqs=CERT_NONEis applied, it overwritesproxy_ssl_context.verify_modein place, and the mutation persists on the reused context.Execution at the vulnerability-class level. With the effective proxy policy now accepting any certificate, the attacker presents a forged or self-signed certificate while impersonating the HTTPS proxy. Since
verify_modeis effectivelyCERT_NONE, the proxy TLS handshake succeeds without validation. No malicious payload is injected by the attacker into the application; the "payload" is the attacker-controlled TLS endpoint itself.Post-exploitation impact. The attacker can observe or modify traffic forwarded through the proxy, and can receive a target TLS client certificate presented during forwarding. CONNECT tunneling remains a separate end-to-end target TLS connection, so that leg is not directly terminated; the compromise centers on the proxy leg, forwarded traffic visibility, and credential/certificate exposure.
No public PoC available; attack chain is inferred from the vulnerability class (CWE-295 improper certificate validation / credential interception via impersonated TLS endpoint).
Impact Assessment
The impact is high for confidentiality and integrity of traffic traversing the affected proxy path, and potentially for credential material: an intercepted proxy leg allows reading or altering forwarded requests, and the target TLS client certificate can be captured. Because the fix is version-gated at 2.8.0 and a broad range (1.26.0 through 2.7.x) of a widely used HTTP client library is affected, blast radius spans any Python service or pipeline that uses an HTTPS proxy with target-server TLS settings — including CI/CD runners, data-ingest jobs, API clients, and microservices in proxied or corporate-network egress paths.
Business impact centers on supply-chain-adjacent data exposure and credential theft rather than remote code execution. There is no persistence or lateral movement implied by the description; the primary risk is a silent, position-dependent interception window that may persist across many reuses of an affected SSL context and therefore go unnoticed. The missing CVSS score and absence of an EPSS value, public PoC, KEV listing, or patch evidence raise uncertainty but do not reduce the underlying exposure for affected deployments. Severity is best framed using the inferred vector CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N, reflecting network reachability, high attack complexity (network position plus specific configuration), and high confidentiality/integrity impact.
Detection Guidance
Sigma Rule
title: urllib3 TLS Proxy Context Not Separated - Suspicious Proxy TLS Behavior
id: 8f2a1c44-9c1b-4d2e-a7f3-202697687a01
status: experimental
description: Detects applications using urllib3 with HTTPS proxies where target-server TLS settings may bleed into proxy verification (CVE-2026-97687).
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-97687
author: valtersit.com
date: 2026/01/01
tags:
- attack.t1190
- cwe.295
logsource:
category: process_creation
product: linux
detection:
selection:
CommandLine|contains:
- 'https_proxy'
- 'HTTPS_PROXY'
- 'use_forwarding_for_https'
condition: selection
fields:
- CommandLine
- ParentImage
falsepositives:
- Legitimate proxy configuration in corporate environments
level: low
YARA Rule
rule CVE_2026_97687_urllib3_proxy_tls_misconfig
{
meta:
author = "valtersit.com"
description = "Detection for urllib3 proxy TLS context separation failure references (CVE-2026-97687)"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-97687"
date = "2026-01-01"
strings:
$s1 = "proxy_ssl_context" ascii
$s2 = "proxy_assert_hostname" ascii
$s3 = "proxy_assert_fingerprint" ascii
$s4 = "use_forwarding_for_https" ascii
$s5 = "cert_reqs" ascii
$s6 = "CERT_NONE" ascii
condition:
(uint16(0) == 0x2133 or filesize > 0) and 3 of them
}
Suricata IDS Rule
alert tls any any -> any any (msg:"CVE-2026-97687 urllib3 HTTPS proxy TLS context separation failure - suspicious proxy certificate"; flow:established,to_server; tls.store; threshold:type both, track by_src, count 5, seconds 60; classtype:attempted-recon; reference:cve,2026-97687; sid:90097687; rev:1;)
Elastic Detection
sequence by host.id with maxspan=5m
[process where process.name in ("python", "python3")
and process.args : ("*https_proxy*", "*HTTPS_PROXY*", "*use_forwarding_for_https*")]
[network where network.direction == "egress"
and network.transport == "tcp"
and network.protocol == "tls"
and not tls.server.certificate_chain : "*trusted*"]
Splunk SPL Query
index=proxy OR index=network sourcetype=tls OR sourcetype=stream:tls
| search (proxy_ssl_context=* OR use_forwarding_for_https=* OR cert_reqs=CERT_NONE)
| stats count by src, dest, dest_port, ssl_issuer, ssl_subject
| where count > 3
| sort - count
Wazuh OSSEC Rule
<group name="urllib3,cve-2026-97687,">
<rule id="100987" level="10">
<decoded_as>json</decoded_as>
<field name="ssl_verify">none</field>
<description>CVE-2026-97687 - urllib3 proxy TLS verification disabled (cert_reqs=CERT_NONE bleed).</description>
<mitre>
<id>T1190</id>
</mitre>
<group>cwe_295,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source).
Immediate mitigations. Do not set
cert_reqs=CERT_NONEor otherwise disable target-server verification when an HTTPS proxy is in use. Where possible, avoid sharing a single reusablessl_contextacross both proxy and target connections; construct separate contexts and do not mutate a context'sverify_modeat runtime. Disableuse_forwarding_for_https=Trueuntil the library is upgraded where that path is not operationally required. Note that these are defensive workarounds inferred from the described trigger conditions; no vendor workaround was published with this CVE.Patch / upgrade steps. The NVD description states the issue is fixed in urllib3 2.8.0. Upgrade any environment using urllib3 in the affected range (1.26.0 through 2.7.x) to 2.8.0 or later. Enumerate dependencies (pip, poetry, conda, vendored copies, container base images) and pin the corrected version. Because no patch artifacts were location-confirmed by tracked sources, verify the release via the official PyPI project page and the upstream repository before rollout.
Long-term hardening. Enforce certificate verification by policy across proxy and target TLS legs; treat
CERT_NONEas a prohibited pattern in code review and CI linting. Maintain separate SSL contexts for proxy and origin connections and forbid in-place mutation of security-relevant attributes. Monitor proxy TLS certificates for unexpected issuers, and restrict egress so tampering requires more than network positioning. Track urllib3 security advisories and this CVE (affecting 1.26.0 through 2.7.x) for updated patch status.
References
- NVD — CVE-2026-97687: https://nvd.nist.gov/vuln/detail/CVE-2026-97687
- urllib3 project (upstream / release notes for 2.8.0): https://urllib3.readthedocs.io/
- PyPI — urllib3 package page: https://pypi.org/project/urllib3/
- CWE-295 Improper Certificate Validation: https://cwe.mitre.org/data/definitions/295.html
- CISA KEV catalog (not listed for this CVE as of report generation): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
No known threat actor campaigns or exploit-in-the-wild evidence were available in the provided data for CVE-2026-97687. No EPSS score has been assigned by FIRST.org, and no public PoC, exploit code, or Nuclei template was identified.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.