Apache HTTP Server HTTP/2 RCE, Fixed in 2.4.71 (CVE-2026-119618)
A thread-safety flaw in Apache HTTP Server's mod_http2 lets an unauthenticated HTTP/2 client corrupt memory and possibly run code; fixed in 2.4.71.
TL;DR
- Apache HTTP Server's mod_http2 writes a synthetic
Content-Lengthheader into a table shared with the connection thread. Apache calls the flaw critical. Red Hat rates it CVSS v3.1 9.8. - Versions 2.4.55 through 2.4.70 are affected when HTTP/2 is enabled with h2 or h2c. Servers that only speak HTTP/1.1 are not affected.
- Red Hat says public research demonstrated a reliable exploit against a default-configured server. No public exploit code is linked, and no in-the-wild use is known; the CVE is not in CISA KEV as of 2026-11-12.
- Upgrade to 2.4.71 or your distribution's fixed package. If you cannot, disable HTTP/2; see "How do I fix it?".
Am I affected?
You are exposed if all of these conditions hold:
- You run Apache HTTP Server 2.4.55 through 2.4.70.
mod_http2is loaded and HTTP/2 is enabled, throughProtocols h2 http/1.1for TLS orh2cfor cleartext.- Untrusted clients can reach that HTTP/2 listener, directly or through a proxy that forwards HTTP/2 to Apache.
Servers configured for HTTP/1.1 only are not affected. Red Hat says RHEL 8 and earlier are not affected because their mod_http2 predates version 2.0.8.
RHEL 9 and RHEL 10 are affected but rated Important. Red Hat says each HTTP/2 stream is allocated from a separate allocator, which substantially increases the complexity of exploitation. The Apache advisory lists mod_h2 2.0.8 through 2.0.42 as affected; the 2.4.71 release carries the fixed module.
| Branch | Affected versions | Fixed version |
|---|---|---|
| Apache HTTP Server 2.4.x | 2.4.55 through 2.4.70 | 2.4.71 |
Apache is used by 20.9% of websites whose web server is known, according to W3Techs. The affected range is a subset of those deployments, because HTTP/2 must be enabled.
Check the installed version and whether HTTP/2 is active:
# Debian and Ubuntu
apache2 -v
apache2ctl -M | grep http2
# RHEL, Fedora and other RPM distributions
httpd -v
httpd -M | grep http2
# The Protocols directive shows whether h2 or h2c is enabled
grep -R "Protocols" /etc/apache2 /etc/httpd 2>/dev/null
For a container, check the running process rather than a freshly pulled image:
docker exec <container> apache2 -v
docker exec <container> apache2ctl -M | grep http2
On RHEL, httpd -v still reports the base 2.4 release after the fix. The security update changes the mod_http2 package, so compare that package with the advisory:
rpm -q mod_http2
RHEL 9.9 carries mod_http2-2.0.26-7.el9_9.1, according to the Red Hat CVE page. RHEL 10.3 carries mod_http2-2.0.29-5.el10_3.1. Earlier mod_http2 builds on those branches are affected.
How do I fix it?
Upgrade to Apache HTTP Server 2.4.71, or install the fixed mod_http2 package your distribution publishes. Red Hat shipped backports on 2026-11-11. Debian's DSA-6620-1 lists apache2 2.4.71 for Debian 13.
- Update the package: ```bash # Debian and Ubuntu sudo apt update sudo apt install --only-upgrade apache2
# RHEL and Fedora
sudo dnf update httpd mod_http2
2. Confirm the fixed build. On Debian 13, `apache2 -v` reports 2.4.71. Older Debian and Ubuntu releases get the fix backported into their existing series, so compare the version shown by `dpkg -s apache2` with the one in the DSA or USN for your release. On RHEL, compare `rpm -q mod_http2` with the package version in the advisory.
3. Restart Apache so the new module is loaded:bash
sudo systemctl restart apache2 # Debian and Ubuntu
sudo systemctl restart httpd # RHEL and Fedora
```
4. Rebuild and recreate every container image that bundles Apache. Pulling a new image is not enough if the running container still uses the old layer.
If you build from source, use the 2.4.71 release tarball from the Apache HTTP Server project.
If you cannot upgrade immediately, disable HTTP/2. The flaw is in the HTTP/2 request path, so removing that path closes it. The cost is the performance benefit of multiplexed requests.
- On Debian and Ubuntu, disable the module and restart:
bash sudo a2dismod http2 sudo systemctl restart apache2 - On RHEL and Fedora, comment out the
LoadModule http2_moduleline and make sureProtocolsdoes not listh2orh2c, then restart:bash sudo systemctl restart httpd - On any distribution, confirm the module is gone with
apache2ctl -M | grep http2orhttpd -M | grep http2. No output means HTTP/2 is off.
A reverse proxy that terminates HTTP/2 and forwards HTTP/1.1 to Apache removes this path at the backend. The proxy itself can still be affected if it runs an affected Apache build. Disabling HTTP/2 is a workaround, not a fix; the patched module is the durable answer.
What is the root cause?
mod_http2 translates HTTP/2 frames into an internal request_rec, and assign_headers() copies the parsed request headers into the request's header table. The bug is that one branch writes a synthetic Content-Length header into the shared source table instead of the per-request copy.
The function lives in modules/http2/h2_request.c. This is the code at the 2.4.70 tag:
static void assign_headers(request_rec *r, const h2_request *req,
int no_body, int is_connect)
{
const char *cl;
r->headers_in = apr_table_clone(r->pool, req->headers);
if (req->authority && !is_connect) {
...
apr_table_setn(r->headers_in, "Host", req->authority);
}
/* Unless we open a byte stream via CONNECT, apply content-length guards. */
if (!is_connect) {
cl = apr_table_get(req->headers, "Content-Length");
if (no_body) {
if (!cl && apr_table_get(req->headers, "Content-Type")) {
/* 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");
}
}
req->headers is the header table parsed for the stream on the connection. r->headers_in is a clone allocated in the request pool, and it is the table Apache modules read. The function receives req as a const h2_request *, so it is not supposed to modify it. The Host branch in the same snippet writes to r->headers_in, which shows the intended target. The Content-Length branch is the outlier.
The trigger is narrow and does not need a body. no_body is true when the client sets END_STREAM on the HEADERS frame, so no request body follows. If that request has a Content-Type and no Content-Length, the branch runs.
apr_table_setn() adds a new key, which grows the table and allocates memory in the table's pool. That pool belongs to the connection and stream, while the write runs on the per-stream worker thread. Red Hat describes the result as a worker thread writing into memory owned by the connection thread through a shared, lock-free allocator.
APR tables and pools are not thread-safe. A concurrent allocation or traversal of the same table can therefore corrupt the heap. The advisory classifies the flaw as a concurrent execution problem with improper synchronization (CWE-362), and Apache's description names assign_headers() directly.
How is it exploited?
- The attacker opens an HTTP/2 connection to the server, over TLS with h2 or in cleartext with h2c.
- The attacker sends many concurrent HEADERS requests on that connection. Each request carries
:method,:path,:authorityand aContent-Type, and sets END_STREAM without aContent-Length. - Each request reaches
assign_headers()on a worker thread withno_bodyset. The worker addsContent-Length: 0to the sharedreq->headerstable. - While the worker allocates in that table, the connection thread and other workers can read or allocate in the same table and pool. The race corrupts heap memory.
- Apache says the corruption can lead to remote code execution. A crash of the worker or the server process is the simpler outcome.
The advisory does not publish exploit code. Red Hat says public research demonstrated a reliable exploit against a default-configured server with mod_http2 enabled, and rates the flaw Critical for that reason. No in-the-wild exploitation is known as of 2026-11-12.
How does the attack flow?
An unauthenticated HTTP/2 client sends a bodyless request with a Content-Type but no Content-Length. The worker's synthetic header write then races the connection thread's allocator until the heap is corrupted.
flowchart LR
A["HTTP/2 client<br/>HEADERS + END_STREAM"] --> B["mod_http2 sets<br/>no_body"]
B --> C["assign_headers()<br/>Content-Type, no Content-Length"]
C --> D["apr_table_setn(req->headers)<br/>shared table, worker thread"]
D --> E["connection thread's<br/>shared allocator"]
E --> F["heap corruption"]
F --> G["crash or remote<br/>code execution"]
What can an attacker do?
An unauthenticated attacker who can reach an HTTP/2 listener can crash the server. If the heap corruption is shaped into a useful primitive, the attacker can execute code as the user that runs Apache. Apache's advisory says the flaw can lead to remote code execution. Red Hat goes further and says successful exploitation allows arbitrary commands, full control of the server process, and access to sensitive data.
Red Hat rates the flaw CVSS v3.1 9.8, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
The conditions are the ones in "Am I affected?": an affected 2.4 release, mod_http2 loaded, HTTP/2 enabled, and network reachability. The attacker needs no account and no user interaction.
Exploitation depends on winning a race, so reliability varies with load, allocator layout and the number of concurrent streams. Red Hat rates RHEL 9 and RHEL 10 Important rather than Critical for that reason, while still listing them as affected.
A crash is a denial of service, not code execution. The sources describe code execution as possible and, in Red Hat's assessment, demonstrated in research. Neither source publishes a working exploit or a victim report.
Why does the fix work?
The patch changes one line in assign_headers() so the synthetic header goes to the per-request clone:
@@ -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");
}
}
r->headers_in is allocated in the request pool and is used only by the worker that handles this stream. The shared req->headers table is no longer modified after the clone is made, so the worker stops writing into the connection thread's memory. The synthetic header still reaches downstream modules, because they read r->headers_in.
The change covers the only write to req->headers in assign_headers(). The other header write in the same function, for Host, already used r->headers_in. The fix does not change the HTTP/2 framing or the request body handling.
How do I check if I was compromised?
No indicators of compromise are published for this flaw. A successful exploit can leave no trace beyond the corrupted memory it used, and a failed attempt may only crash a worker.
Check the Apache error log for crashes and unexpected child exits, especially on servers that had HTTP/2 exposed before you patched:
grep -Ei "segfault|signal 11|child pid .* exit|AH00051" /var/log/apache2/error.log
grep -Ei "segfault|signal 11|child pid .* exit|AH00051" /var/log/httpd/error_log
On a systemd host, list core dumps for the Apache binary:
coredumpctl list apache2
coredumpctl list httpd
A crash is a lead, not proof of exploitation, because other bugs and resource limits can also kill a worker. If you find repeated crashes on an HTTP/2 server that ran an affected build, preserve the logs and the core dumps before you restart. Treat the host as possibly compromised until you have reviewed it.
Timeline
- 2026-10-26: Anthropic's OSS Scanner reports the flaw to the Apache security team as ANT-2026-MAPKT6MZ.
- 2026-11-03: Anthony Weems and Simon Scannell of Google Cloud Vulnerability Research report the flaw independently.
- 2026-11-09: The fix lands on the 2.4.x branch as commit
824beab, a cherry-pick of the master commit5ed3928. - 2026-11-11: Apache releases 2.4.71 and publishes the CVE-2026-119618 advisory. Red Hat publishes its fixed
mod_http2packages and advisories the same day.
FAQ
Does this affect HTTP/1.1-only servers?
No. The flaw is in the HTTP/2 request path. A server that loads mod_http2 but only negotiates HTTP/1.1 does not reach assign_headers().
My reverse proxy terminates TLS. Is my Apache backend exposed?
It depends on the protocol between the proxy and Apache. If the proxy forwards HTTP/2, the backend is exposed. If it forwards HTTP/1.1, this path is closed at the backend, but the proxy itself may run an affected Apache build.
Is there a public exploit?
No public exploit code is linked from the Apache advisory or the CVE record. Red Hat says public research demonstrated a reliable exploit against a default-configured server with mod_http2 enabled.
Is CVE-2026-119618 in CISA KEV?
No. The CVE was not in the CISA Known Exploited Vulnerabilities catalog as of 2026-11-12, and no in-the-wild exploitation is known.
Which RHEL versions are affected?
RHEL 9 and RHEL 10 are affected and rated Important. RHEL 8 and earlier are not affected because their mod_http2 predates 2.0.8. Install the mod_http2 package version listed in the Red Hat advisory for your branch.
Why does httpd -v still show 2.4.57 after the RHEL update?
Red Hat backported the fix into the mod_http2 package instead of rebasing httpd. Check rpm -q mod_http2 against the fixed package version, not the httpd version string.
References
- Apache HTTP Server security page, CVE-2026-119618 advisory, published 2026-11-11: https://httpd.apache.org/security/vulnerabilities_24.html (checked November 12, 2026)
- CVE-2026-119618 record, Apache Software Foundation CNA, published 2026-11-11: https://www.cve.org/CVERecord?id=CVE-2026-119618 (checked November 12, 2026)
- Fix commit on the 2.4.x branch, 824beab, 2026-11-09: https://github.com/apache/httpd/commit/824beab9b9424d6cfb29595248fdbf6c3dddeab1 (checked November 12, 2026)
- Upstream fix commit on master, 5ed3928, 2026-11-09: https://github.com/apache/httpd/commit/5ed39287660daacd1233cb9bbc984b25fa9a4fe3 (checked November 12, 2026)
- Red Hat CVE-2026-119618 page, CVSS v3.1 9.8 and fixed mod_http2 packages, published 2026-11-11: https://access.redhat.com/security/cve/CVE-2026-119618 (checked November 12, 2026)
- Debian security tracker for CVE-2026-119618, DSA-6620-1 and fixed apache2 2.4.71: https://security-tracker.debian.org/tracker/CVE-2026-119618 (checked November 12, 2026)
- W3Techs, Apache usage share, 20.9% of websites whose web server is known: https://w3techs.com/technologies/details/ws-apache (checked November 12, 2026)