curl · Report #3671818
CVE-2026-6276: stale custom cookie host causes cookie leak
How it was found
Summary:
libcurl keeps a stale data->state.aptr.cookiehost after a request that uses a custom Host: header. On later requests on the same easy handle, when no custom Host: is used, libcurl still reuses that stale value for outgoing cookie selection (lib/http.c:2560-2563) and incoming Set-Cookie attribution (lib/http.c:3561-3567). The stale state is set from the custom-Host: path in lib/http.c:2030-2065 and is not cleared in the non-custom-host path at lib/http.c:2075-2089. I reproduced this on curl 8.19.0 / libcurl 8.19.0 on x86_64 Linux. In the attached PoC, a cookie seeded for victim.internal is leaked to attacker.test, the attacker injects poison=EVIL into the victim jar, and that poisoned cookie is then replayed back to victim.internal on a third request. A ZIP with the PoC source, server script, captured logs, and a fuller write-up is attached.
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:
- Start the attached local server:
python3 -u stale_cookiehost_server.py 18083 - Build the attached PoC:
cc poc_stale_cookiehost.c -o poc_stale_cookiehost $(curl-config --cflags --libs) - Run the PoC:
./poc_stale_cookiehost - The PoC uses one easy handle with an in-memory cookie jar, sends request 1 with
Host: victim.internal, removes that custom header for request 2 toattacker.test, and then sends request 3 back tovictim.internal. - Observe the server log:
{"host": "victim.internal", "path": "/seed", "cookie": null}{"host": "attacker.test:18083", "path": "/attack", "cookie": "sid=SECRET123"}{"host": "victim.internal:18083", "path": "/check", "cookie": "poison=EVIL; sid=SECRET123"} - Observe the cookie jar output:
after request 1:
sid=SECRET123is stored forvictim.internalafter request 2:poison=EVILis also stored forvictim.internalafter request 3: the poisoned cookie is replayed back tovictim.internal
Impact
Summary:
This breaks cookie origin isolation across reused easy handles. An attacker-controlled origin can receive cookies that belong to a different origin, inject its own cookies into that victim origin's jar, and have those attacker-controlled cookies replayed back to the victim on subsequent requests. This is both a confidentiality break and an integrity break.