HexBrain

curl · Report #4112912

CVE-2026-111481: server-set cookie still aborts cookie jar

Validstatus
lowseverity
1upvotes
26 Oct 2026disclosed

How it was found

Suggested CWE: CWE-1284: Improper Validation of Specified Quantity in Input (H1 didn't let me chose this)

AI Disclaimer:

I've written this report with the help of AI, please feel free to let me know if I made a mistake, I've read the final revision of this report a few times to ensure it was solid but my understanding of the inner workings of curl is where I can fall short.

Summary:

The fix for CVE-2026-92386 (445aa87e13) lets the cookie file parser accept lines up to MAX_COOKIE_LINE + 48 bytes, so a line of 5047 or more characters still fails to load. A saved cookie line also holds the domain and the path, and neither counts toward the Set-Cookie length limit when the server leaves them out of the header. A server can set a cookie with a 4000-byte value and no Path, at a URL with a 1500-byte path, and curl saves a 5539-character line. Since 3f0629ca4 (8.18.0), a cookie file load error fails the transfer: the next curl run that loads the jar fails at once with "(100) A value or data field grew larger than allowed" and sends no request. If the same file is also passed to -c, that failed run rewrites the jar with no cookies at all. That is harsher than the advisory's "silently abort parsing", and released 8.22.0 behaves the same with these steps.

I would have liked to report this sooner, before 8.23.0 was out, but I've only managed to finish this now and I still have a lot of other curl CVEs to fix for the Debian package.

Affected version

Reproduced the same way with three builds on Debian forky/sid x86_64:

  • curl master 9a6d4ffc1 (2026-10-13), debug build;
  • the curl-8_22_0 tag, built from git;
  • Debian's curl 8.23.0~rc3-1 package, built from 8.23.0-rc3.

The master build's curl -V:

curl 8.23.0-DEV (x86_64-pc-linux-gnu) libcurl/8.23.0-DEV OpenSSL/3.6.5 zlib/1.3.2 brotli/1.2.0 zstd/1.5.7 libidn2/2.3.8 libssh2/1.11.1 nghttp2/1.70.0 OpenLDAP/2.6.14
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt mqtts pop3 pop3s rtsp scp sftp smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli Debug HSTS HTTP2 HTTPS-proxy IDN IPv6 Largefile libz SSL threadsafe UnixSockets zstd

Steps To Reproduce:

The attached hdrsrv.py is a small HTTP server. It answers any path containing /set with the header given on its command line, and any other path with a plain 200.

python3 hdrsrv.py 8080 srv.log Set-Cookie \
  "big=$(python3 -c 'print("v"*4000)'); Max-Age=86400" &
printf '127.0.0.1\tFALSE\t/\tFALSE\t2000000000\tone\t1\n' > jar
printf '127.0.0.1\tFALSE\t/\tFALSE\t2000000000\ttwo\t2\n' >> jar

curl -b jar -c jar "http://127.0.0.1:8080/$(python3 -c 'print("a"*1500)')/set"
# exit code 0; after the header comments, the first cookie line is now
# the 5539-character "big" cookie (cookie_output() writes newest first)

curl -b jar http://127.0.0.1:8080/check
# exit code 100, no request reaches the server; the same on every later run

curl -b jar -c jar http://127.0.0.1:8080/check
# exit code 100 again, and the jar is rewritten with no cookies

Impact

Summary:

Any server the user visits can make every later curl run that reads the cookie file fail, until the user removes the line by hand. With the common -b jar -c jar setup, the next run also erases every stored cookie, for all sites. A new cookie is written first, so the server does control where its line lands. That contradicts the advisory's note that it cannot; a cookie that replaces an existing one keeps its old position. This is the CVE-2026-92386 impact, still reachable after the fix, and in 8.18.0 and later the result is a failed transfer and an emptied jar rather than skipped cookies.

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