curl · Report #3920276
Cookie jar load skips public suffix check on PSL builds
How it was found
On curl 8.21.0 with libpsl (official curl.se 8.21.0_6 win64, Features: PSL), HTTP Set-Cookie: Domain=co.uk is dropped in verbose. The same cookie loaded from a Netscape jar file or a Set-Cookie: line in that file is accepted and later sent to unrelated hosts under the suffix (bank.co.uk, other.co.uk).
Root cause: is_public_suffix() in lib/cookie.c only calls libpsl when the setting-host domain argument is non-NULL (line 815). cookie_load() passes NULL at line 1179. CURLOPT_COOKIELIST uses the same path. docs/cmdline-opts/cookie.md says PSL builds discard suffix-domain cookies on --cookie file load; that check is missing here.
Version: curl 8.21.0 (x86_64-w64-mingw32), libcurl/8.21.0, libpsl/0.23.0, Windows 11.
Control (HTTP - works):
- Server returns Set-Cookie: trk=http; Domain=co.uk; Path=/
- curl -v -c jar -b jar --resolve evil.co.uk:9999:127.0.0.1 http://evil.co.uk:9999/
- Verbose: must not set cookies for 'co.uk'. Request to bank.co.uk with -b jar sends no Cookie: header.
Bug (jar - broken):
- cookies.txt (tab-separated Netscape format):
Netscape HTTP Cookie File
.co.uk TRUE / FALSE 0 trk planted 2. curl -v -b cookies.txt --resolve bank.co.uk:9998:127.0.0.1 http://bank.co.uk:9998/ 3. Request includes Cookie: trk=planted. Same jar also sends to other.co.uk.
Also reproduces with Set-Cookie: trk=viafile; Domain=co.uk; Path=/ as the only line in the file. PoC attached runs control + bug twice on localhost.
(AI for report polishing)
Impact
If untrusted data can be merged into a cookie jar (shared file, -b -, CURLOPT_COOKIELIST, app importing a foreign cookie export), an attacker can plant a supercookie for a public suffix (co.uk, github.io, etc.). curl then attaches it on requests to unrelated sites under that suffix. Same impact class as prior PSL supercookie fixes on live Set-Cookie, but the gap is jar/COOKIELIST import where domain is NULL and the PSL gate is skipped.