Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 4 min read

1 line fixed Apache's critical RCE. I read the patch

1 line fixed Apache's critical RCE. I read the patch Apache fixed a critical remote code execution bug in mod_http2 yesterday with a one-line patch. The vulnerable range covers every 2.4.55 through 2.4.70 release, and

1 line fixed Apache's critical RCE. I read the patch

Apache fixed a critical remote code execution bug in mod_http2 yesterday with a one-line patch. The vulnerable range covers every 2.4.55 through 2.4.70 release, and there is no public exploit yet β€” but the patch itself tells you exactly where to look.

The bug, as Apache describes it

CVE-2026-119618 is a race condition in assign_headers() in mod_http2. Concurrent threads sharing a resource without proper synchronization can corrupt heap memory, and heap corruption in the web server process is arbitrary code execution β€” remote, unauthenticated. Apache's advisory lists it as critical, fixed in 2.4.71, released November 11, 2026. The standalone mod_h2 module from GitHub is affected from 2.0.8 through 2.0.42.

The timeline is short. Anthropic's OSS Scanner found it first and reported it on October 26; Google Cloud's Vulnerability Research team (Anthony Weems and Simon Scannell) reported it independently on November 3. Sixteen days from first report to a released fix, and the fix commit is 824beab, dated November 11.

The entire fix

Here is the complete diff of the security fix, from the 2.4.70 to 2.4.71 tree:

--- a/modules/http2/h2_request.c
+++ b/modules/http2/h2_request.c
@@ -350,7 +350,7 @@ static void assign_headers(request_rec *r, const h2_request *req,
                 /* If we have a content-type, but already seen eos, no more
                  * data will come. Signal a zero content length explicitly.
                  */
-                apr_table_setn(req->headers, "Content-Length", "0");
+                apr_table_setn(r->headers_in, "Content-Length", "0");

One token changed: req->headers became r->headers_in. That is the whole patch.

To see why it matters, look at the function it sits in. assign_headers() starts by cloning the shared header table into a per-request copy:

r->headers_in = apr_table_clone(r->pool, req->headers);

Everything after that line reads from req->headers and writes to r->headers_in β€” the clone. Everywhere except one place. In the branch where the client already signaled end-of-stream, sent a Content-Type, but sent no Content-Length, the code synthesized a zero content length and wrote it back into req->headers β€” the shared original, not the clone.

req is the h2_request, the parsed HTTP/2 request object. HTTP/2 is a multiplexed protocol: many streams share one connection, and the request object is the shared resource the advisory names. A write to its header table from one thread while another thread reads or clones the same table is a data race on an apr_table_t, and a torn table operation is heap corruption. The fix writes the synthesized header into the per-request clone, where it always belonged. Every other write in the function already did that; this was the one that didn't.

Two things make this bug nastier than it looks. First, the trigger is an ordinary-looking request: content type present, no body, end-of-stream already seen. Nothing exotic. Second, the vulnerable code path runs before the request reaches your application β€” it is in header assignment, so no application-level check can save you. The only mitigations are the upgrade or turning HTTP/2 off (Protocols http/1.1).

I tried to measure exposure from the outside. You mostly can't.

I probed 63 domains β€” web servers, hosting panels, CMS projects, CDNs β€” with curl over HTTP/2, recording the Server header and the negotiated protocol:

probed:              63
reachable:           38
returned any Server:  8
advertised Apache:    1  (redhat.com, no version, HTTP/1.1)
versioned Apache:     0

Zero versioned Apache servers in the sample. That is not evidence nobody runs Apache β€” it is evidence the outside world stopped advertising versions years ago. Server headers are suppressed, proxied, or generic now, so a version-string census of the public web tells you almost nothing about who is on 2.4.55–2.4.70. The honest measurement here is a negative one: from the outside, you cannot tell who is vulnerable, which is exactly why this class of bug is dangerous. The exposure number worth quoting is Wiz's, and it is theirs, not mine: Wiz says 64% of cloud environments have resources vulnerable to this CVE, and 51% have publicly exposed instances β€” vendor telemetry, not something I can independently verify, and it does not account for configuration (HTTP/2 has to be on).

One more check came back empty in a telling way: Ubuntu's security tracker has no page for CVE-2026-119618 yet β€” it 404s as of this morning. The CVE was disclosed yesterday; distro packaging takes time. If you run Apache from a distro package, check your distro's tracker rather than assuming the fix has landed.

The rest of 2.4.71

The release fixes three CVEs: this critical one, an important NULL pointer dereference in mod_md (CVE-2026-106023, child process crash), and one low-severity issue. The changelog also carries unrelated fixes β€” a mod_deflate gzip extra-field sign extension, a mod_dav lock-timeout overflow, asterisk-form OPTIONS handling in mod_http2.

The lesson I keep coming back to: the scariest bugs are not the ones with the biggest diffs. A race condition that hands out remote code execution hid in a function that was otherwise careful β€” clone first, write to the clone β€” and the one line that broke the pattern was a synthesized Content-Length: 0 in a corner case nobody would think to audit. One line in, one line out.

Sources: Apache HTTP Server security advisory, vulnerabilities fixed in 2.4.71 (httpd.apache.org, released 2026-11-11); the fix commit 824beab and the 2.4.70/2.4.71 trees on github.com/apache/httpd (modules/http2/h2_request.c, assign_headers()); Wiz blog, "Critical RCE Vulnerability in Apache HTTP Server" (CVE-2026-119618, November 11, 2026); the 63-domain probe is my own run, November 12, 2026 β€” 38 reachable, 8 returned a Server header, 1 advertised Apache with no version. No public exploit exists as of publication, and no in-the-wild exploitation has been reported.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.