curl · Report #3952619
Domainless COOKIEFILE cookie leaks to unrelated IP-literal hosts
How it was found
When curl loads a cookie file written as raw HTTP Set-Cookie: header lines and a line has no Domain attribute, the cookie is stored with co->domain == NULL, because a file import has no request-host to scope it to. On the send side, Curl_cookie_getlist accepts any cookie in the bucket whose domain is NULL before it ever compares the request host (the !co->domain || short-circuit at lib/cookie.c:1340) and cookiehash() places both NULL-domain cookies and numeric-IP hosts in the same bucket 0 (lib/cookie.c:216). The result is that a domainless cookie from a file gets attached to requests for unrelated IP-literal hosts. An attacker who can steer the client into following a redirect to an IP literal can harvest whatever credential that cookie carries.
Steps to reproduce (tested with curl 8.7.1 on macOS)
Start a listener on port 8888.
printf 'HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n' | nc -l 8888
(On Linux / GNU netcat, the port is passed as nc -l -p 8888 instead.)
Step 1: write a cookie file in HTTP Set-Cookie: header format, with no Domain attribute:
printf 'Set-Cookie: SBF_SECRET=secret; Path=/\r\n' > c.txt
Step 2: load that file and make a request to an IP-literal host:
curl -v -b c.txt http://127.0.0.1:8888/
curl's verbose output shows > Cookie: SBF_SECRET=secret. The domainless cookie was sent to 127.0.0.1, even though the CURLOPT_COOKIEFILE.md docs say it must not be.
Negative control (optional): repeat step 2 against a DNS name that resolves to the same IP, and the cookie is not sent, which isolates the leak to the IP-literal path:
curl -v -b c.txt --resolve example.test:8888:127.0.0.1 http://example.test:8888/
Impact
This is a cross-origin leak of a host-scoped credential. Cookies loaded via COOKIEFILE frequently carry session IDs, API tokens, or other secrets. This bug attaches such a cookie to a request for an unrelated host, contradicting curl's documented COOKIEFILE behavior and RFC 6265 §5.3/§5.4 cookie scoping.
The victim runs curl with such a cookie jar and -L, and an endpoint the attacker controls or influences (an open redirect on a trusted site, or any followed hop) points curl at http://<attacker-ip>/. The domainless cookie is then sent to that attacker-controlled IP in a plaintext Cookie: header and the attacker can replays whatever it protects (session ID, API token, CSRF secret) to act as the victim.