Yaamlabs
Vulnerabilities

curl CVE-2026-92392: find every libcurl before you patch

A malicious HTTP/2 server can trigger a use-after-free in curl 8.12.0 to 8.22.0 during uploads. Fixed builds, the HTTP/1.1 workaround, and how to find every copy.

By Yaali. October 16, 2026, 6 min read, Vulnerabilities, Patching.

Cover illustration of a client terminal sending data streams to a distant server, with one stream cut off and a broken memory block still tethered to the client, with the Yaamlabs logo and the text: A malicious HTTP/2 server can crash or hijack curl, 8.12.0 to 8.22.0, curl and libcurl affected

The curl project released curl 8.23.0 on October 14 with a fix for CVE-2026-92392, a use-after-free in HTTP/2 upload handling. A server that resets a stream at the right moment during an upload leaves curl holding a pointer to memory it has already freed. The flaw is in curl and libcurl 8.12.0 through 8.22.0, so it affects the command-line tool and every program that links the library. Versions before 8.12.0 never had the vulnerable code.

The curl project grades it High. The advisory says the bug can be turned into remote code execution on the client, but only under a long list of strict conditions, and that a crash is the more likely result of an attack. No exploitation in the wild has been reported. The work for most teams is finding every copy of libcurl they run, because it is built into far more software than the curl binary.

How CVE-2026-92392 is triggered: curl uploads over HTTP/2, the server sets the flow-control window to zero, sends part of a response, then resets the stream with REFUSED_STREAM or HTTP_1_1_REQUIRED, and libcurl later follows a stale pointer to a freed transfer handle

How it works

HTTP/2 carries many requests over one connection as numbered streams. Each side controls how fast the other may send through a flow-control window: a server that sets the window to zero tells the client to stop sending body data until further notice. Either side can also end a single stream with an RST_STREAM frame and a reason code, while the connection itself stays open.

Daniel Stenberg, curl's lead developer, describes the sequence. curl starts an upload of roughly 135 KB to a malicious server. The server pauses it by setting the window to zero, sends back part of a response, and then resets the stream with the reason REFUSED_STREAM or HTTP_1_1_REQUIRED. curl tears down the transfer but leaves a lingering pointer to the easy handle, the struct Curl_easy object that represents one transfer in libcurl. When the application frees that handle and then cleans up the multi handle (the object that drives several transfers at once), libcurl uses the dangling pointer.

The upload is what makes the zero window useful to the attacker: curl still has request body data queued for a stream the server has already killed. The fix was written by Stefan Eissing. Stenberg says the project is also moving away from keeping internal handle pointers at all, in favour of transfer identifiers that are looked up when needed, which he calls "a tiny bit slower" but more foolproof.

The bug was reported on September 15 through HackerOne by Luna Tong of Anthropic, credited in the advisory as "Luna with Claude, Anthropic". Stenberg says it was found with Anthropic's OSS Scanner. The project shortened its release cycle from eight to six weeks to ship the fix sooner.

How realistic is code execution

The proof of concept goes further than a crash. It makes curl leak local memory addresses, which helps defeat address space layout randomisation (ASLR), then gets server-supplied data written into the freed memory so that a function pointer the attacker controls is called. The curl advisory lists what that needed: the exact curl version and structure layout, the CPU architecture, a known libc allocator and heap layout, predictable nghttp2 and OpenSSL TLS 1.3 behaviour around session tickets, a pinned CA bundle, two parallel transfers with predictable timing, calibrated libc offsets, and a command of about 23 bytes.

Two conditions narrow it further. The client has to choose to upload to the attacker's server, and that server has to present a certificate curl accepts. Stenberg writes that "the chance for a successful attack is slim", which is why the project graded it High rather than Critical.

So the question for each system is who controls the HTTPS servers it uploads to. Think of webhook senders that POST to customer-supplied URLs, CI jobs that upload artifacts or test reports to third-party endpoints, backup and log shipping agents, and integrations that post to a URL a user typed in. A server you run yourself is a low risk. An upload target any tenant or user can set is the case to fix first.

Severity scores do not agree

The curl project does not publish CVSS scores and rates the flaw High on its own four-level scale. SecurityOnline lists a CVSS 3 score of 8.1. Ubuntu rates it High priority following upstream, with no number, and other databases still showed it as unscored when this was written. If your patch policy keys off CVSS, treat 8.1 as a third-party figure that may change.

What to do

Fixed curl versions, distribution package status and five steps: inventory, check bundled copies, upgrade, restart long-running processes, and force HTTP/1.1 where you cannot upgrade yet

1. Upgrade to a fixed build

Upstream, move to curl 8.23.0. The project lists 8.14.3, 8.16.2 and 8.20.2 as fixed builds on those branches. The patch commit is 8b0744af5b1b631da5b938ca31c if you build curl yourself.

Distribution packages, as of October 16:

  • Debian 13 (trixie): fixed in 8.14.1-2+deb13u7 through DSA-6558-1. Debian 12 (bookworm) ships 7.88.1 and is not affected.
  • Ubuntu 26.04 LTS: fixed in 8.18.0-1ubuntu2.8 (USN-8927-1). Ubuntu 24.04, 22.04 and older LTS releases are not affected.

For other distributions, check the vendor's CVE page: vendors backport fixes into older version strings.

2. Find every copy

The curl package is the easy part. Look for libcurl in these places too:

  • The host: curl --version for the tool, ldconfig -p | grep libcurl for shared libraries the dynamic linker knows about, and ldd /path/to/binary | grep curl for a given program.
  • Language bindings: PHP's curl extension (php -r 'echo curl_version()["version"];'), Python's pycurl (python3 -c "import pycurl; print(pycurl.version)"), and Git, whose HTTPS transport uses libcurl (ldd $(git --exec-path)/git-remote-http).
  • Container images and CI runners: each image carries its own libcurl. Scan them with your image scanner, or search an SBOM (software bill of materials) for curl and libcurl components between 8.12.0 and 8.22.0.
  • Statically linked or bundled copies in vendor software and appliances. These do not show up in ldconfig, so ask the vendor whether the product ships libcurl and in which version.

3. Restart what has the old library loaded

Upgrading the package does not fix a process that loaded the old libcurl.so at start-up. After the update, lsof -n | grep 'libcurl.*(deleted)' lists processes still mapping the replaced file, and needrestart on Debian and Ubuntu reports the services to restart. Rebuild and redeploy container images, since a running container keeps the library it was built with.

4. If you cannot upgrade today, stop using HTTP/2

The advisory's workaround is to not use HTTP/2. For the tool, add --http1.1. In code, set CURLOPT_HTTP_VERSION to CURL_HTTP_VERSION_1_1 on every easy handle, since libcurl negotiates HTTP/2 over TLS by default when it is built with HTTP/2 support. Prioritise the jobs that upload to servers you do not control.

5. Checking for an attempt

There is no published indicator of compromise. A failed attempt most likely looks like a crash, so look for segmentation faults in curl or in services that use libcurl (journalctl -k | grep segfault, or coredumpctl list) around uploads to external hosts.

The library is the inventory problem

curl 8.23.0 fixes 24 vulnerabilities in total, 23 of them rated low, and removes SMB support, so the update is worth taking on its own. The harder lesson is that a package-level vulnerability scan only sees the copies a package manager installed. Images, bundled vendor builds and long-running processes each need their own check.

Our attack surface management work keeps an inventory of the software you expose and the components inside it, and our cloud and Kubernetes security reviews cover the container images and CI runners where stray copies of libcurl tend to sit. Open the chat and Yaali, our AI agent, will pass your question to an engineer.


Sources: curl advisory CVE-2026-92392, Daniel Stenberg: A UAF turned RCE, The Hacker News, Cyber Kendra, Threat Landscape, SecurityOnline, Debian security tracker, Ubuntu CVE page.

Read next

Back to the blog, or tell us about your system in the chat. Yaali, our AI agent, answers first and brings in an engineer.