A medium-severity vulnerability in CPython’s HTTP proxy tunneling code leaves Windows users open to CR/LF injection attacks, according to an advisory published in April 2026. Tracked as CVE-2026-1502, the flaw allows attackers to inject carriage return and line feed characters into proxy CONNECT requests, potentially hijacking web sessions or poisoning caches.
The vulnerability exists because Python’s http.client module, which handles HTTP connections, failed to properly sanitize the hostname when establishing a tunnel through an HTTP proxy. This oversight affects Windows systems specifically due to platform-dependent behaviors in CPython’s networking stack. Developers and system administrators running Python applications that use a proxy on Windows should act immediately.
What Is CR/LF Injection?
CR/LF injection is a classic web application security weakness where an attacker inserts carriage return (CR, \r) and line feed (LF, ) characters into an HTTP request. These characters mark the end of a header line in the HTTP protocol. By injecting them into parts of a request—such as a URL, cookie, or form field—an attacker can prematurely terminate the current header and insert additional headers or even split the response. This can lead to HTTP response splitting, cache poisoning, cross-site scripting (XSS), and proxy route manipulation.
In the context of HTTP proxy tunneling, the CONNECT method is used to establish a TCP tunnel to a remote server through a proxy. The initial request looks like this:
CONNECT target.example.com:443 HTTP/1.1
Host: target.example.com:443
Proxy-Authorization: Basic ...
If the target part of the CONNECT request contains CR/LF characters, an attacker could inject extra headers or break out of the request entirely. For example, a hostname like evil.com\r
Injected-Header: value\r
could cause the proxy to interpret the injected header as part of the request, potentially altering its behavior.
How Python’s Proxy Tunneling Works
Python’s standard library includes http.client.HTTPConnection (and its HTTPS variant) which supports forwarding requests through an HTTP proxy. When a proxy is configured, the connection’s tunnel() method is called before sending the actual request. This method constructs and sends the CONNECT request to the proxy, using the target host and port provided by the caller. After the proxy responds with a 200 status code, the tunnel is established and the client can proceed with end-to-end encrypted communication.
The vulnerability in CVE-2026-1502 arises because the hostname passed to tunnel() was not adequately checked for control characters. On Windows, the underlying C implementation of CPython’s networking routines may have handled line endings or string termination differently, allowing CR and LF bytes to remain in the hostname string instead of being stripped or rejected. This platform-specific oversight meant that only Windows users were affected, while Unix-like systems—where Python’s networking code took a stricter approach—were not susceptible to the same injection vector.
Impact on Windows Environments
The Windows-specific nature of this flaw is particularly concerning for enterprise and corporate settings, where HTTP proxies are ubiquitous. Many Python tools and frameworks—ranging from data science libraries to DevOps automation scripts—rely on the standard library’s proxy support. If an attacker can control the hostname passed to a proxied connection (e.g., via a URL parameter, user input, or a malicious redirect), they could exploit this vulnerability to:
- Smuggle requests or responses: By injecting additional headers, an attacker could trick the proxy into caching poisoned content or routing requests to an unintended server.
- Bypass security controls: A carefully crafted CR/LF injection might allow an attacker to escape proxy-based filtering or authentication checks.
- Conduct SSRF attacks: In combination with other weaknesses, this flaw could be used to force the proxy to connect to internal addresses.
The CVSS score for CVE-2026-1502 has been assessed as medium severity, reflecting that exploitation generally requires the ability to influence the hostname used in a proxy connection and that the impact is limited to HTTP-level attacks. However, in environments where Python applications are exposed to untrusted input and use a corporate proxy, the risk escalates.
Affected Versions and Patch
At the time of disclosure, the vulnerability affected all supported CPython versions on Windows prior to the April 2026 security release. The Python Software Foundation (PSF) quickly released patches for Python 3.11.x, 3.12.x, and 3.13.x. Users of end-of-life versions such as 3.10 and earlier are particularly urged to upgrade, as they will not receive an official fix.
The patch adds a validation step in the tunnel() method to reject any hostnames containing \r or characters. The check is performed early in the connection establishment process, before the CONNECT request is sent. Developers reviewing the official diff will see an additional if block that raises a ValueError if control characters are detected in the host string.
How to Check If You’re Vulnerable
To determine whether your Windows system is running a vulnerable CPython version, open a command prompt and execute:
python -c "import http.client;
c = http.client.HTTPSConnection('bad\r
X-Injected: true', timeout=5, context='checkhostname=False');
c.settunnel('target.example.com', 443);
c.connect()"
If this snippet raises a ValueError instead of attempting a connection, your Python installation has been patched. Otherwise, you are vulnerable. Note that testing should be done in a controlled environment, as sending malformed requests could trigger alerts or interfere with proxy servers.
Mitigation and Workarounds
The primary mitigation is to upgrade CPython to the latest patch level. For users who cannot immediately update, consider these workarounds:
- Input sanitization: Before passing any hostname to
settunnel()or to a library that uses it internally, strip out\rand characters. A simplehost.replace('\r', '').replace(' ', '')is sufficient, though a more thorough validation is recommended. - Avoid the default proxy handler: If your application uses
urllib.requestwith a proxy, switch to a third-party HTTP client likeurllib3(which by then will have its own patch) orrequestswith a custom transport adapter. These libraries often implement their own header validation. - Network-level defenses: Ensure that your organization’s proxy server itself is configured to reject malformed CONNECT requests. While this does not eliminate the vulnerability in Python, it reduces the attack surface.
Real-World Scenarios
Imagine a Windows-based build server that pulls dependencies from a private PyPI repository. The server uses a corporate proxy, and the pip tool is configured to use it. If a malicious package name or URL on a public index contains CR/LF characters, a carefully crafted pip install could trigger the vulnerability during proxy tunnel negotiation, potentially redirecting the connection. Although Python packaging tools have their own security layers, this weakness adds another risk vector.
Similarly, consider a monitoring script that uses http.client to check the health of internal web services via a proxy. If the script accepts destination URLs from an external source without rigorous validation, an attacker could exploit CVE-2026-1502 to force connections to attacker-controlled endpoints or inject bogus headers into the proxy’s request chain.
Broader Implications for Windows Security
CVE-2026-1502 highlights an ongoing challenge in cross-platform development: differences in how operating systems handle low-level details like string termination and newline characters can lead to subtle security bugs. While the HTTP protocol mandates CR-LF line endings regardless of the platform, Python’s internals on Windows apparently allowed those bytes to persist when they should have been stripped. This is not the first such case—and it won’t be the last—underscoring the need for rigorous fuzzing and platform-specific testing of network libraries.
For Windows users, this CVE is a reminder that even mature, widely trusted software stacks like CPython merit ongoing scrutiny. The combination of corporate proxies and legacy scripts creates a vast attack surface that is often overlooked. Security teams should inventory all Python applications that pass through an HTTP proxy and validate their hostname handling.
Conclusion
CVE-2026-1502 may carry a medium severity rating, but in Windows enterprise environments it represents a very real attack vector. The simplicity of the fix—adding a few lines of input validation—belies the potential damage of successful exploitation. Patch your CPython installations now, and if you maintain Python code that interacts with proxies, audit every place where a hostname is assembled from untrusted data. In a world where supply chain attacks are increasingly common, even a legacy protocol bug can become a stepping stone to deeper compromise.