CVE-2026-6276: stale custom cookie host causes cookie leak
Low
Vulnerability Details
## 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:
1. Start the attached local server:
`python3 -u stale_cookiehost_server.py 18083`
2. Build the attached PoC:
`cc poc_stale_cookiehost.c -o poc_stale_cookiehost $(curl-config --cflags --libs)`
3. Run the PoC:
`./poc_stale_cookiehost`
4. 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 to `attacker.test`, and then sends request 3 back to `victim.internal`.
5. 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"}`
6. Observe the cookie jar output:
after request 1: `sid=SECRET123` is stored for `victim.internal`
after request 2: `poison=EVIL` is also stored for `victim.internal`
after request 3: the poisoned cookie is replayed back to `victim.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.
Actions
View on HackerOneReport Stats
- Report ID: 3671818
- State: Closed
- Substate: resolved