HexBrain

curl · Report #3671818

CVE-2026-6276: stale custom cookie host causes cookie leak

Validstatus
lowseverity
24upvotes
29 Apr 2026disclosed

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:

  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.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original