← Back to Feed CACHED · 2026-10-15 17:03:02 · CACHE_KEY CVE-2026-92392
CVE-2026-92392 · CWE-416 · Disclosed 2026-10-14

curl HTTP/2 upload use-after-free via RST_STREAM mishandling

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Like a rigged ATM that only steals from people who deposit exactly $135 in cash

CVE-2026-92392 is a use-after-free in curl/libcurl's HTTP/2 upload path, affecting versions 8.12.0 through 8.22.0. When a malicious HTTP/2 server receives an upload, it can pause the transfer by zeroing the flow-control window, return partial response data, then send an RST_STREAM frame with reason HTTP_1_1_REQUIRED or REFUSED_STREAM. This causes curl to free a struct Curl_easy object while the multi handle still holds a dangling pointer. Subsequent cleanup downloads attacker-controlled data into the freed memory, overwriting a function pointer. The researcher (Luna Tong at Anthropic, using an AI-assisted OSS scanner) proved this can be chained into remote code execution, though the payload window is only ~23 bytes and the upload must be approximately 135 KB. The fix is a 6-line reorder in multi_done() in lib/multi.c. Fixed upstream in 8.23.0, with backports to 8.20.2, 8.16.2, and 8.14.3.

The vendor rates this HIGH at 8.1 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H), and on paper that is defensible — AC:H already accounts for the heap-grooming difficulty. But the CVSS vector overstates real-world risk in one critical way: the attacker must be the HTTP/2 server the victim is uploading to (or MITM the connection with a valid TLS certificate). That is not 'no privileges required' in the intuitive sense — it presupposes the attacker controls infrastructure the victim trusts enough to upload data to. Combined with the 135 KB upload-size constraint, architecture-specific heap layout requirements, and the fact that most exploitation attempts will produce a crash rather than code execution, the effective severity is a notch below the vendor label. We downgrade to HIGH 6.8 rather than MEDIUM because curl is the most widely deployed HTTP client library on the planet and the RCE is proven, not theoretical.

"Proven client-side RCE in curl, but attacker must own the server you upload to"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Victim initiates HTTP/2 upload to attacker-controlled server

The victim's curl/libcurl client must connect over HTTP/2 and begin a PUT or POST upload of approximately 135 KB to a server the attacker controls or has compromised. This can occur via CI/CD artifact pushes, API integrations, webhook deliveries, or any automated upload workflow. The server must present a valid TLS certificate for the target hostname.
Conditions required:
  • Victim uses curl/libcurl 8.12.0–8.22.0
  • HTTP/2 is negotiated (requires nghttp2 compiled in)
  • Victim uploads ~135 KB of data to attacker-controlled endpoint
Where this breaks in practice:
  • Attacker must control or compromise the upload target server — this is not a drive-by attack
  • Most enterprise upload targets are internal artifact stores, not arbitrary internet servers
  • Certificate validation means the attacker needs a cert for the exact hostname the victim trusts
Detection/coverage: Network monitoring for unexpected HTTP/2 RST_STREAM frames with reason codes 0xd (HTTP_1_1_REQUIRED) or 0x7 (REFUSED_STREAM) during active uploads. No mainstream IDS signature exists yet.
STEP 02

Server pauses upload and returns partial response

The malicious server zeros the HTTP/2 flow-control window to pause the upload mid-stream, then sends partial response headers and body data. This sets up the race condition where curl's multi handle will attempt to process the response while the transfer is in a half-completed state.
Conditions required:
  • Server implements custom HTTP/2 frame-level manipulation
  • Timing must be precise to hit the vulnerable code path
Where this breaks in practice:
  • Requires a custom HTTP/2 server implementation — standard web servers cannot produce this sequence
  • Timing sensitivity means network jitter can break the chain
STEP 03

Server sends RST_STREAM to trigger use-after-free

The server sends RST_STREAM with reason HTTP_1_1_REQUIRED or REFUSED_STREAM. This causes curl to free the struct Curl_easy but leave a dangling pointer in the multi handle. The freed memory region is now available for reallocation.
Conditions required:
  • RST_STREAM must arrive after the upload is paused but before full cleanup
  • The specific reason codes HTTP_1_1_REQUIRED or REFUSED_STREAM must be used
Where this breaks in practice:
  • If the frame arrives too early or too late, curl handles it correctly or simply crashes without exploitable state
Detection/coverage: AddressSanitizer (ASan) builds of curl will catch the UAF at this stage with heap-use-after-free diagnostics.
STEP 04

Attacker-controlled data overwrites freed memory

During multi handle cleanup, libcurl downloads the server's remaining response data into the freed struct Curl_easy memory region. The attacker crafts this data to overwrite a function pointer within the structure. The payload is limited to approximately 23 bytes, requiring precise knowledge of the target's architecture, libc allocator behavior, and heap layout.
Conditions required:
  • Attacker knows target architecture (x86_64, aarch64, etc.)
  • Heap layout must be favorable — depends on libc version, TLS library, and application-specific allocations
  • Payload must fit in ~23 bytes
Where this breaks in practice:
  • Heap layout varies dramatically across Linux distributions, libc versions (glibc, musl), TLS backends (OpenSSL, GnuTLS, wolfSSL), and application embedding patterns
  • ASLR and stack canaries further complicate reliable exploitation
  • The 23-byte payload constraint severely limits what can be achieved — most real attacks will crash the process
Detection/coverage: Runtime memory-safety tools (ASan, Valgrind) detect the corruption. Crash telemetry showing SIGSEGV in multi_done() or nearby functions is a strong indicator.
STEP 05

Code execution on victim client

If the function pointer overwrite succeeds, the attacker achieves code execution in the context of the curl/libcurl process. This runs with whatever privileges the uploading application has — potentially root in CI/CD runners or service accounts in automated pipelines. From here, the attacker can pivot within the victim's environment.
Conditions required:
  • All prior heap-grooming conditions must align
  • Function pointer must be called before any integrity check catches the corruption
Where this breaks in practice:
  • Daniel Stenberg's advisory explicitly states 'the most likely outcome of an attempted attack is rather just a crash'
  • The attacker gets one shot per upload — a crash terminates the process and alerts monitoring
  • Proven in lab conditions but no known successful weaponization in the wild
Detection/coverage: EDR/XDR should detect anomalous child process spawning from curl processes. Process crash monitoring (coredumpctl, crashpad) will capture failed attempts.
03 · Compensating Control

1
HIGH 6.8→IGNORE 0.0
SEVERITY REDUCED
Force HTTP/1.1 for upload operations — Set CURLOPT_HTTP_VERSION to CURL_HTTP_VERSION_1_1 or pass --http1.1 on the CLI for all upload (PUT/POST with body) operations. This completely eliminates the attack surface because the vulnerability is exclusively in the HTTP/2 RST_STREAM handling path. Deploy within 30 days per the noisgate mitigation SLA for HIGH. Audit automation scripts, CI/CD configs, and application code that uses libcurl for uploads.
2
HIGH 6.8→IGNORE 0.0
SEVERITY REDUCED
Patch curl/libcurl to fixed version — Upgrade to curl 8.23.0, or apply distribution backports: Debian trixie 8.14.1-2+deb13u7, Ubuntu 26.04 8.18.0-1ubuntu2.8. Debian bookworm and Ubuntu ≤24.04 ship curl <8.12.0 and are not affected. For container images, rebuild base images with the updated package. Deploy within 180 days per the noisgate remediation SLA for HIGH.
3
HIGH 6.8→LOW 3.2
SEVERITY REDUCED
Restrict upload destinations to allowlisted endpoints — Use network policy (firewall rules, service mesh policy, egress proxy) to ensure CI/CD runners and automated upload workflows can only reach trusted, internally-managed artifact stores. This breaks the attack chain at step 1 by preventing uploads to attacker-controlled servers. Does not help against compromised internal servers but dramatically reduces the attack surface.
4
HIGH 6.8→HIGH 6.0
Enable crash telemetry and anomaly detection on upload-heavy systems — Configure coredump collection (systemd-coredump, Google Crashpad) and EDR alerting for unexpected SIGSEGV or SIGABRT in curl/libcurl processes. Since most exploitation attempts produce a crash, this provides early warning of active targeting even before a successful exploit lands.
What doesn't work
  • WAF/IPS in front of the victim's outbound connections — this is a client-side vulnerability triggered by server responses, not by malicious requests. Traditional WAF rules inspect inbound traffic to servers and have no visibility into HTTP/2 frame-level responses received by a curl client.
  • Disabling HTTP/2 at the network level (e.g., ALPN stripping) — while theoretically this works, ALPN stripping on a TLS-inspecting proxy breaks legitimate HTTP/2 traffic site-wide and is operationally destructive. Use the per-client CURLOPT_HTTP_VERSION approach instead.
  • Certificate pinning alone — pinning prevents MITM but does not help if the attacker has compromised the legitimate upload target server itself. It is additive but not sufficient.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not listed in CISA KEV as of 2026-10-16. No campaigns, no GreyNoise tags, no threat-intel reports of active exploitation. Daniel Stenberg's advisory and blog post confirm no known attacks.
Proof-of-concept availabilityDefensive checker only. ashu7ank/CVE-2026-92392 on GitHub is a Python-based exposure scanner (0 stars, 9 commits) — it explicitly contains *no shellcode, no memory manipulation, no RCE payload*. It performs passive version checks and a loopback HTTP/2 protocol probe. Listed on pocindex.io via GitHub source only. No Nuclei template, no ExploitDB entry, no Metasploit module. Anthropic's internal PoC (used to prove RCE to the curl team) has not been published.
EPSS0.00226 (0.226%) — bottom quartile. Indicates extremely low predicted probability of exploitation in the next 30 days. Consistent with the high complexity and client-side attack model.
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.1 HIGH. The AC:H reflects the heap-grooming difficulty. PR:N is technically correct (no auth on the victim side) but misleading — the attacker must control the server. UI:N is debatable since an upload must be initiated.
Affected versionscurl/libcurl 8.12.0 through 8.22.0. Introduced by commit cd9107e0128. Branch-specific affected ranges: 8.12.0–8.14.2, 8.15.0–8.16.1, 8.17.0–8.20.1, 8.21.0–8.22.0.
Fixed versionsUpstream 8.23.0 (2026-10-14). Maintenance backports: 8.14.3, 8.16.2, 8.20.2. Debian trixie: 8.14.1-2+deb13u7 (DSA-6558-1). Ubuntu 26.04: 8.18.0-1ubuntu2.8 (USN-8927-1). Debian bookworm (7.88.x) and Ubuntu 24.04/22.04 are not affected — the vulnerable code was introduced in 8.12.0.
Scanning/exposure dataNo GreyNoise, Shodan, or Censys scanning activity associated with this CVE. This is expected — it is a client-side vulnerability, not a remotely scannable server flaw. Internet-facing exposure metrics do not apply in the traditional sense.
Disclosure timelineReported 2026-09-15 by Luna Tong (Anthropic OSS Scanner). Fixed and disclosed 2026-10-14 with curl 8.23.0 release. 29-day coordinated disclosure window. Patch authored by Stefan Eissing.
Researcher/discoveryLuna Tong, Anthropic — discovered using Anthropic's opt-in AI-assisted OSS Scanner (code-named AISLE). Of the 24 CVEs fixed in curl 8.23.0, AI-assisted research found 20, including this one — the only HIGH. First HIGH-severity curl flaw since the SOCKS5 heap overflow (CVE-2023-38545) in October 2023.
HTTP/2 requirementVulnerability requires nghttp2 to be compiled into curl. Curl builds without HTTP/2 support (no --with-nghttp2 at compile time, or Features: line missing HTTP2) are not affected regardless of version.

Sources.

  1. curl official advisory (CVE-2026-92392)
  2. Daniel Stenberg blog — A UAF turned RCE
  3. Debian security tracker
  4. Ubuntu security notice (USN-8927-1)
  5. ashu7ank/CVE-2026-92392 defensive checker (GitHub)
  6. pocindex.io entry
  7. Cyber Kendra writeup
  8. SecurityOnline coverage
05 · The Call

Final Verdict
= UNCHANGED to HIGH (6.8/10)

Why this verdict

  • Client-side attack model is the dominant friction: The attacker must control or compromise the HTTP/2 server the victim uploads to, or perform a MITM with a valid TLS certificate. This is not a remotely exploitable server flaw — it inverts the typical attack direction. The CVSS PR:N is technically correct but functionally misleading; the attacker needs an infrastructure position, not merely network access.
  • Heap-grooming constraints compound beyond AC:H: The ~135 KB upload size requirement, architecture-specific payload, 23-byte payload limit, and libc/TLS-backend-dependent heap layout mean that a working exploit must be tailored per-target-environment. Daniel Stenberg explicitly states most attempts will crash the process rather than achieve RCE. The CVSS AC:H partially captures this, but the real-world difficulty exceeds what a single complexity toggle can express.
  • No weaponized PoC, no wild exploitation, rock-bottom EPSS: The only public repository is a defensive scanner with zero offensive capability. Anthropic's proof-of-RCE has not been released. EPSS at 0.226% and no KEV listing confirm the threat-intel community sees minimal near-term exploitation probability.
  • Role multiplier: curl/libcurl is present on virtually every Linux host, macOS system, and container image. *Low-value role (workstations, dev machines):* exploitation requires the developer to upload ~135 KB to a malicious server over HTTP/2 — low probability, blast radius is one workstation. *Typical role (application servers making API calls):* most API calls are downloads/GETs, not uploads of the right size — low probability. *High-value role (CI/CD runners uploading artifacts):* if a CI/CD pipeline uploads build artifacts to a compromised artifact store, the attacker achieves code execution on the runner, potentially pivoting to supply-chain compromise. CI/CD runners represent >1% of curl's installed base, and the outcome is supply-chain-scale. This sets the verdict floor at HIGH. However, the chain requires the artifact store to already be compromised (a separate, severe breach), and the heap-grooming requirements make reliable exploitation unlikely even then.
  • Net assessment: The vendor's 8.1 overstates real-world risk because CVSS cannot encode 'attacker must be the server you voluntarily upload to.' We downgrade to 6.8 but hold at HIGH due to the CI/CD supply-chain floor and the proven (if difficult) RCE chain in the world's most deployed HTTP library.

Why not higher?

A CRITICAL rating would require either reliable exploitation without extraordinary preconditions, active exploitation in the wild, or a weaponized public PoC. None of these apply. The 23-byte payload limit, 135 KB upload-size constraint, environment-specific heap layout requirements, and the fact that crashes far outnumber successful exploits all argue against CRITICAL. The attack also requires the victim to upload to an attacker-controlled server, which is a fundamentally harder attacker position than most CRITICAL-rated CVEs demand.

Why not lower?

Despite the substantial friction, a proven use-after-free → RCE chain in curl/libcurl — the HTTP client library embedded in billions of devices, every major Linux distribution, every container base image, and most CI/CD pipelines — cannot be rated MEDIUM. The supply-chain implications of RCE in CI/CD upload paths set a HIGH floor. The vulnerability class (UAF with function-pointer overwrite) is well-understood by sophisticated attackers, and the constraint space, while narrow, is enumerable. History shows that 'too hard to exploit' curl bugs (cf. CVE-2023-38545 SOCKS5 overflow) attract sustained research attention once disclosed.

06 · Verification

Crowdsourced verification payload.

Run this script on each target host where curl or libcurl may be installed. It requires no special privileges — just read access to the curl binary. Invoke as: bash check_cve_2026_92392.sh or bash check_cve_2026_92392.sh /path/to/curl if your curl is not in $PATH.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_92392.sh — Detect CVE-2026-92392 exposure
# curl HTTP/2 upload use-after-free (affects 8.12.0 – 8.22.0)
# Usage: bash check_cve_2026_92392.sh [/path/to/curl]
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

CURL_BIN="${1:-curl}"

if ! command -v "$CURL_BIN" &>/dev/null; then
  echo "UNKNOWN — curl binary not found at '$CURL_BIN'"
  exit 2
fi

VERSION_LINE=$("$CURL_BIN" --version 2>/dev/null | head -1)
VERSION=$(echo "$VERSION_LINE" | grep -oP '\d+\.\d+\.\d+' | head -1)

if [[ -z "$VERSION" ]]; then
  echo "UNKNOWN — could not parse curl version from: $VERSION_LINE"
  exit 2
fi

# Check HTTP/2 support — if absent, not vulnerable regardless of version
FEATURES=$("$CURL_BIN" --version 2>/dev/null)
if ! echo "$FEATURES" | grep -qi 'HTTP2\|nghttp2'; then
  echo "PATCHED — curl $VERSION does not have HTTP/2 support compiled in (not affected)"
  exit 0
fi

# Version comparison helper
ver_to_int() {
  local IFS='.'
  read -r major minor patch <<< "$1"
  printf '%d%03d%03d' "${major}" "${minor}" "${patch}"
}

V=$(ver_to_int "$VERSION")

# Affected ranges:
#   8.12.0 – 8.14.2
#   8.15.0 – 8.16.1
#   8.17.0 – 8.20.1
#   8.21.0 – 8.22.0
# Fixed: 8.14.3, 8.16.2, 8.20.2, 8.23.0+

VULN=false

if   [[ $V -ge $(ver_to_int 8.12.0) && $V -le $(ver_to_int 8.14.2) ]]; then
  VULN=true
elif [[ $V -ge $(ver_to_int 8.15.0) && $V -le $(ver_to_int 8.16.1) ]]; then
  VULN=true
elif [[ $V -ge $(ver_to_int 8.17.0) && $V -le $(ver_to_int 8.20.1) ]]; then
  VULN=true
elif [[ $V -ge $(ver_to_int 8.21.0) && $V -le $(ver_to_int 8.22.0) ]]; then
  VULN=true
fi

if $VULN; then
  echo "VULNERABLE — curl $VERSION with HTTP/2 support is in the affected range (CVE-2026-92392)"
  exit 1
else
  echo "PATCHED — curl $VERSION is not in the affected range"
  exit 0
fi