Apache HTTP/2 Double-Free RCE: One Version Affected, Six Days to Patch

Apache HTTP Server 2.4.66 ships with a double-free in mod_http2 — exploitable on default Debian builds and patched six days later in 2.4.67.

Share
Line-art illustration of a rack-mounted web server with HTTP/2 data streams converging at a fractured input port, depicting Apache CVE-2026-23918.

A double-free in mod_http2 sat in production Apache for six days before a single-version patch landed — and the proof-of-concept fits in a handful of HTTP/2 frames.

WAKEFIELD, MA — The Apache HTTP Server project disclosed CVE-2026-23918 this week, a critical memory-corruption flaw in the mod_http2 module that affects exactly one shipping release — 2.4.66 — and is patched in 2.4.67. CVSS scored the bug at 8.8, and researchers Pawel Dmitruk and Krzysztof Strzalkowski demonstrated remote code execution on a default Debian configuration. The window from public release to patch was six days.

The trigger is a double-free in h2_mplx.c — Apache's HTTP/2 multiplexer — exercised by a client that opens a stream with a HEADERS frame and immediately follows with RST_STREAM before the worker thread completes setup. On builds that use the mmap memory allocator (Debian's default), the freed-and-reallocated region overlaps with worker structures, giving an attacker control of a function pointer. MPM prefork builds, which fork a process per request rather than sharing a thread pool, are unaffected because the freed memory never reaches another request.

Vulnerability Profile
DetailInformation
CVECVE-2026-23918
SeverityCVSS 8.8 (High) — network attack vector, no authentication, low complexity
Affected SoftwareApache HTTP Server 2.4.66 with mod_http2 enabled
Fixed VersionApache HTTP Server 2.4.67 (released May 14, 2026)
TriggerHTTP/2 HEADERS frame followed by RST_STREAM before stream setup completes
Root CauseDouble-free in h2_mplx.c stream-pool reclamation path
Exploitable Pathmmap memory allocator + worker thread MPM (Debian default)
Unaffected BuildsMPM prefork; non-default malloc implementations
ResearchersPawel Dmitruk and Krzysztof Strzalkowski
Disclosure WindowSix days from 2.4.66 release to 2.4.67 patch

How the Bug Got Shipped

Apache 2.4.66 included a refactor of the HTTP/2 stream-pool reclamation code in h2_mplx.c. The intent was straightforward — when a client cancels a stream via RST_STREAM, the multiplexer should release the stream's per-request memory pool back to the worker. The refactor introduced a path where, if the cancellation arrived before the worker had finished initializing the stream, two separate cleanup routines could both reach the same pool pointer.

The race was small and the failure mode was quiet on most setups. On builds that use the glibc default allocator, the second free triggered a hard abort that crashed the worker — visible, but not exploitable beyond denial of service. The combination that turned it into remote code execution was specific: APR's mmap-based allocator, which Debian and several derivatives enable by default, places freed regions back on a reuse list that the worker draws from for new request structures. A double-free on that list lets an attacker arrange for two live pointers into the same chunk, which is a textbook setup for overwriting a function pointer.

Why It Took Six Days

Dmitruk and Strzalkowski reported the bug to Apache on May 8. The project's security team confirmed reproduction within hours and had a candidate patch in 2.4.67 by May 11. The remaining time went to validating that the fix didn't regress the stream-pool path under load — HTTP/2 multiplexing is one of the more invasive subsystems in mod_http2, and the maintainers wanted a clean test cycle before cutting a release.

The disclosure window is unusually tight for an Apache critical. The project typically takes two to four weeks to coordinate a patch release, especially when a fix touches connection handling. Six days suggests the maintainers judged the exploit primitive serious enough — and reproduction simple enough — that holding back was the bigger risk.

What Defenders Are Up Against

The exploit fits in a few HTTP/2 frames over a single TLS connection. There's no authentication step, no protocol-level negotiation that a WAF can match on, and no anomalous header structure — just the cancellation timing. Detection signatures that rely on payload shape will miss it. Detection that watches for high rates of RST_STREAM relative to opened streams may catch exploitation attempts but will also catch a lot of legitimate impatient clients.

Apache rarely sits exposed by itself. The realistic blast radius is the long tail of internal apps, dashboards, and self-hosted services running behind 2.4.66 — many of which sit on cloud images that auto-updated from 2.4.65 last week and won't auto-update again until next week's package cycle. The version-pin window is where this bug lives, and it's the same dynamic that left the Cisco Catalyst SD-WAN CVSS 10.0 bug exposed for weeks before fleet-wide patching caught up.


The CyberSignal Analysis

Signal 01: Single-Version Vulnerabilities Are a Patch-Triage Trap

Most vulnerability response playbooks weight severity by exposure — "how much of our fleet is affected." CVE-2026-23918 inverts that calculation. The bug exists in exactly one release; if you skipped 2.4.66 you're fine. But that creates a triage trap: teams looking at the CVE feed see "Apache HTTP Server" and reflexively prioritize. The actually-vulnerable surface is narrower than the headline implies, and the wide-but-not-exploitable population is much larger than the narrow-and-exploitable one. Spending the same response cycle on 2.4.65 boxes and 2.4.66 boxes wastes the response budget. Patch triage that doesn't read past the product name will misallocate effort here — the same trap teams fell into during the Palo Alto Mythos 75-flaw scan, where the headline number was less important than the version-specific subset.

Signal 02: Allocator Choice Is a Quiet Determinant of Exploitability

The same source code is non-exploitable under glibc malloc and exploitable under APR mmap. That kind of allocator-dependent severity is becoming more common — recent NGINX Rift coverage flagged a similar pattern in the NGINX worker pool. For defenders, the implication is that the question "are we vulnerable to CVE-X" can't always be answered from version data alone. Build flags, distro defaults, and allocator configuration are part of the answer. For attackers, it means the same source patch can shield some downstream consumers while leaving others fully exposed — and the exposed ones tend to be the ones running stock distro packages.

What to Do This Week

  1. Inventory Apache HTTP Server installs and flag any running 2.4.66 specifically. The wider 2.4.x population can wait for normal patch cycles. The 2.4.66 instances are this week's work.
  2. Upgrade to 2.4.67 on every 2.4.66 host. The patch is single-version and the upstream changelog is narrow — regression risk for non-mod_http2 functionality is low.
  3. If you can't patch immediately and you control the config, disable mod_http2 on affected hosts. HTTP/1.1 clients are unaffected; performance degrades but the attack surface closes.
  4. Check whether your distro packages Apache with the mmap allocator (Debian, Ubuntu, and several downstream images do). If so, exploitation is realistic and patching is the only durable mitigation.
  5. Add a detection rule for elevated RST_STREAM rates per connection on Apache hosts. It will false-positive on impatient clients, but it's the cheapest signal for exploitation attempts before patches land.

Sources

TypeSource
PrimaryApache HTTP Server Security Advisory — CVE-2026-23918
CVE RecordCVE-2026-23918 — Apache HTTP Server mod_http2 Double-Free
ResearchApache httpd Commit Reference — mod_http2 h2_mplx.c Fix
CoverageThe Hacker News — Apache HTTP/2 Double-Free RCE
RelatedThe CyberSignal — NGINX Rift: Allocator-Dependent Exploitability
RelatedThe CyberSignal — Cisco SD-WAN CVE-2026-20182 Under Active Attack
RelatedThe CyberSignal — Microsoft MDASH and Palo Alto Mythos AI Vuln Discovery