curl · Report #3677759
CVE-2026-6429: netrc credential leak with reused proxy connection
How it was found
Summary:
libcurl can leak .netrc-derived host Authorization credentials across redirected hosts when an HTTP proxy connection is reused. In the PoC, .netrc contains credentials only for a.test, but after a.test redirects to b.test and then c.test over the same keep-alive proxy connection, libcurl sends Authorization: Basic dXNlckE6cGFzc0E= to b.test and c.test. The leaked header is Authorization, not Proxy-Authorization, and the attached controls show the leak disappears when connection reuse is forbidden, when each request uses a new easy handle, and when the same redirect flow is run without a proxy. The issue appears to involve the .netrc / redirect / proxy connection reuse path in lib/url.c and lib/http.c. I reproduced this on curl 8.19.0 / libcurl 8.19.0 on x86_64 Linux. An attachment with the PoC source, server scripts, .netrc file, and captured logs is included.
Affected version
Reproduced on:
curl 8.19.0 (x86_64-pc-linux-gnu) libcurl/8.19.0 OpenSSL/3.5.5 zlib/1.3.1 brotli/1.2.0 zstd/1.5.7 libidn2/2.3.8 libpsl/0.21.5 libssh2/1.11.1 nghttp2/1.68.1 ngtcp2/1.21.0 nghttp3/1.15.0 librtmp/2.3 mit-krb5/1.22.1 OpenLDAP/2.6.10
Platform:
Linux x86_64
Steps To Reproduce:
- Ensure the attached
.netrcfile contains only:machine a.test login userA password passA - Start the proxy/server:
python3 -u netrc_proxy_redirect_server.py 18085 - Start the no-proxy origin control server:
python3 -u netrc_origin_redirect_server.py 18087 - Build the PoC:
cc poc_netrc_proxy_redirect.c -o poc_netrc_proxy_redirect $(curl-config --cflags --libs) - Run the PoC:
./poc_netrc_proxy_redirect - Observe the base case proxy log.
a.test,b.test, andc.testall use the sameclient_port, showing proxy connection reuse, and the same hostAuthorizationheader is sent to all three hosts:{"client_port": 49048, "host": "a.test", "path": "http://a.test/start", "authorization": "Basic dXNlckE6cGFzc0E=", "proxy_authorization": null}{"client_port": 49048, "host": "b.test", "path": "http://b.test/second", "authorization": "Basic dXNlckE6cGFzc0E=", "proxy_authorization": null}{"client_port": 49048, "host": "c.test", "path": "http://c.test/third", "authorization": "Basic dXNlckE6cGFzc0E=", "proxy_authorization": null} - Observe the controls:
- with
CURLOPT_FORBID_REUSE=1,b.testandc.testreceive noAuthorization - with a new easy handle per request,
b.testandc.testreceive noAuthorization - without a proxy,
b.testandc.testreceive noAuthorization
- with
- The attached logs also show that
Proxy-Authorizationis alwaysnull, so the leaked header is the target-hostAuthorizationheader, not proxy credentials.
Impact
Summary:
An attacker-controlled redirected host reachable through the same HTTP proxy connection can receive .netrc credentials that belong to a different host. This is a cross-host credential boundary break: credentials configured only for a.test are sent as host Authorization to b.test and c.test, even though .netrc has no entries for those hosts. In applications that use libcurl with .netrc, redirects, and HTTP proxy connection reuse, this can expose reusable Basic credentials to an unintended origin.