# Apache 2.4.71 fixes an HTTP/2 RCE (CVE-2026-119618): which hops to check

> Apache 2.4.55 to 2.4.70 with h2 or h2c enabled via Protocols is exposed to CVE-2026-119618. Check each hop and the origin, then patch or turn HTTP/2 off.

Source: https://sheng.page/en/posts/apache-http2-cve-2026-119618-what-to-check/ · Published: 2026-11-12 · Author: Sheng

Apache HTTP Server 2.4.71 came out on 11 November 2026 and fixes CVE-2026-119618, a remote code execution flaw in mod_http2 that upstream rates critical. A server is in scope when three things are true together: the version is between 2.4.55 and 2.4.70, mod_http2 is loaded, and `Protocols` enables h2 or h2c. Servers that only speak HTTP/1.1 are not affected.

Start by reading the `Protocols` setting on every host, then use connection tests and the origin access logs to confirm what each hop actually negotiates. If HTTP/2 is on and your distribution has no fixed package yet, turn HTTP/2 off for now. As of 17:00 Taipei time on 12 November I found no authoritative report of exploitation in the wild, and the latest CISA KEV catalogue does not list the CVE. Red Hat does say public research has demonstrated a reliable exploit, so patch affected services now, or apply the temporary mitigation, without waiting for attacks to be confirmed.

## What has to be true

Upstream gives the affected range as 2.4.55 to 2.4.70, and 2.0.8 to 2.0.42 for the standalone mod_h2 releases on GitHub. Red Hat's analysis adds the condition operators can check on the host: only servers with HTTP/2 enabled through the `Protocols` directive are affected, whether that is h2 or h2c. The root cause is a worker thread that writes into memory owned by the connection thread, through a shared allocator used without locking. Red Hat scores it CVSS 3.1 9.8, and an attacker needs no authentication.

That leaves four separate things to confirm: the version string, whether the module is loaded, what `Protocols` says, and whether the distribution has backported the fix. `httpd -v` alone cannot tell you whether a deployment is affected. A server in that version range is unaffected if the module is not loaded or `Protocols` enables neither h2 nor h2c. A distribution package can keep an old version string after the fix has been backported. The official Docker image shows the first case: httpd:2.4.70 and httpd:2.4.71 both use mpm_event as the default MPM, the http2_module `LoadModule` line is commented out, and there is no `Protocols` directive. If you changed that configuration, or run an image somebody else built, check again.

The same release fixes a NULL pointer dereference in mod_md (CVE-2026-106023, important, 2.4.30 to 2.4.70) and a one-byte stack buffer overwrite in mod_vhost_alias (CVE-2026-109163, low, 2.4.69 and 2.4.70). Turning HTTP/2 off deals with mod_http2 only, so the upgrade still has to happen.

## The hop behind the CDN

The usual first reaction is that a CDN or reverse proxy sits in front. Check which protocol the front layer speaks to the origin, and whether the origin can be reached without going through it. A client speaking HTTP/2 to the edge says nothing about whether the origin has HTTP/2 enabled.

The check below ran on OrbStack with the official images. It only looks at what each hop negotiates, sends no attack traffic and does not reproduce the vulnerability. The origin is 2.4.70 with `Protocols h2c http/1.1`, fronted by nginx with `http2 on;` and a `proxy_pass`. The first `sed` loads the module and the `printf` after it deliberately enables h2c for the test. The mitigation is the later line that sets `Protocols` to `http/1.1`, so take care which one you copy:

```sh
# Only checks which protocol each hop speaks; no attack traffic
docker network create h2check
docker run --detach --name origin --network h2check httpd:2.4.70 sh -c '
  sed -i "s/^#LoadModule http2_module/LoadModule http2_module/" conf/httpd.conf
  printf "ServerName origin\nProtocols h2c http/1.1\nLogFormat \"%%h %%>s proto=%%H\" p\nCustomLog /proc/self/fd/1 p\n" >> conf/httpd.conf
  exec httpd-foreground'
# nginx.conf: events {} http { server { listen 80; http2 on; location / { proxy_pass http://origin:80; } } }
docker run --detach --name front --network h2check --volume "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" nginx:1.29
sleep 3

c() { docker run --rm --network h2check curlimages/curl:8.17.0 --silent --output /dev/null --write-out "$1 -> HTTP/%{http_version} %{http_code}\n" "${@:2}"; }
c "client->front" --http2-prior-knowledge http://front/
c "client->origin direct" --http2-prior-knowledge http://origin/
docker logs origin 2>&1 | grep proto=

# Mitigation: keep HTTP/1.1 only, then confirm
docker exec origin sh -c 'sed -i "s/^Protocols .*/Protocols http\/1.1/" conf/httpd.conf && httpd -t && httpd -k graceful'
sleep 2
c "client->origin direct (--http2)" --http2 http://origin/
```

Output, with the three leading network and container ID lines left out:

```text
client->front -> HTTP/2 200
client->origin direct -> HTTP/2 200
192.168.97.3 200 proto=HTTP/1.1
192.168.97.4 200 proto=HTTP/2.0
Syntax OK
client->origin direct (--http2) -> HTTP/1.1 200
```

The client speaks HTTP/2 to nginx, and the request nginx forwards is logged at the origin as HTTP/1.1, so that path never touches mod_http2. Reach the same origin directly and the log says HTTP/2.0, which is the hop to worry about. After `Protocols http/1.1` and a graceful restart, `curl --http2` gets HTTP/1.1, and a separate `--http2-prior-knowledge` attempt fails with curl exit code 16. The graceful restart here only shows what new connections get. Old processes finish the connections they already hold, so established HTTP/2 connections stay on the old configuration, and a real mitigation needs a full stop and start.

I used h2c to avoid setting up certificates. Production is mostly h2 over TLS negotiated with ALPN, and the reasoning is the same. Mainstream browsers only do HTTP/2 over TLS, but curl will talk h2c, so do not skip the plaintext port because browsers ignore it. "The CDN is in front" stays an assumption until a log or a curl run backs it up.

## Where each distribution stands

| Target | Status when checked |
| --- | --- |
| Upstream Apache HTTP Server | 2.4.71 released 2026-11-11; 2.4.55 to 2.4.70 affected |
| RHEL 8 and earlier | Not affected; mod_http2 before 2.0.8 lacks the code |
| RHEL 9, RHEL 10 | RHSAs released 2026-11-11, e.g. RHSA-2026:98981 (mod_http2-2.0.26-7.el9_9.1) and RHSA-2026:98978 (mod_http2-2.0.29-5.el10_3.1) |
| Debian | bookworm, trixie and forky open; sid at 2.4.71-1 |
| Ubuntu | No fixed package in the archive yet; whether jammy is affected is for Ubuntu to say (unverified) |
| Standalone mod_h2 | 2.0.8 to 2.0.42 affected; repository archived and unmaintained, latest is v2.0.42, no fix |

Red Hat rates RHEL 9 and 10 as Important because their mod_http2 packages allocate each stream from a separate allocator, which makes exploitation considerably harder. EUS and similar streams received RHSAs the same day. JBoss Core Services and Hardened Images are marked Affected with no fix listed yet. Debian's bookworm is at 2.4.68-1~deb12u1 and trixie at 2.4.68-1~deb13u1 (trixie-security at 2.4.69-1~deb13u1), all inside the range. Ubuntu's newest security and updates uploads date from 9 to 10 November, before the upstream announcement, and the changelogs for noble 2.4.58-1ubuntu8.18, resolute 2.4.66-2ubuntu2.7 and stonking 2.4.68-1ubuntu6.1 do not mention this CVE. jammy is on the 2.4.52 series, below the upstream range, but whether the affected code was backported is Ubuntu's call, and the Ubuntu CVE page failed to load when I checked. The standalone mod_h2 README states the repository is archived and no longer maintained, with the module now living in the Apache httpd project. Anyone building and loading that version will not get a new release and should move to a module patched by upstream or the distribution.

## Public research, attacks in the wild and KEV are three things

The flaw was reported on 26 October and 3 November by Anthropic's OSS Scanner (ANT-2026-MAPKT6MZ) and by Anthony Weems and Simon Scannell of Google Cloud Vulnerability Research. Red Hat writes that public research has demonstrated a reliable exploit against a default-configured server with mod_http2 enabled. That shows it can be done, though I found no authoritative source saying anyone is doing it. Vulnerability aggregators already list a repository labelled as a PoC. I have not verified it and do not link to it.

The latest KEV catalogue is 2026.11.10, released on 10 November with 1,779 entries, and CVE-2026-119618 is not in it. That edition predates the Apache announcement by a day, so the most it shows is that the CVE was not listed then. The lack of confirmed exploitation is a poor reason to put the work off.

## Inventory and update

1. List every host and container running Apache, including origins behind a CDN, internal services and images built by someone else.
2. On each one, check version, modules and `Protocols` separately, at the global level and in every virtual host, since a virtual host can override it. For distribution packages, read the vendor advisory for backports.
3. curl only sees the hop it connects to. Use it on the public entry point and on the origin directly, bypassing the CDN and keeping the real hostname. Test h2c on port 80 and any listener reachable only from inside as well. For what the CDN speaks to the origin, read the CDN configuration and the origin access log.
4. Where a fixed package exists, update and do a full restart. `httpd -v` reads the new binary on disk and proves nothing about the process holding the port, so check that the process started after the package was updated.
5. Where your distribution branch has no fix yet, set `Protocols` to `http/1.1` globally and in every virtual host, run `httpd -t`, then stop and start fully, and make sure the old processes are gone. Confirm from the loaded configuration that no listener still offers HTTP/2, with curl as a supporting check.
6. Put `Protocols` back only after the package is confirmed fixed.

The commands below are read-only. Names vary by distribution and I have not tested each variant. `curl --http2` falls back to HTTP/1.1 on its own when negotiation fails, so `2` means this hop has HTTP/2, while `1.1` only means it was not negotiated this time. Run `curl -V` first to confirm your curl was built with HTTP2:

```sh
# Version, modules and configuration are three separate checks
httpd -v || apache2 -v
httpd -M 2>/dev/null | grep -E 'http2|mpm_' || apache2ctl -M 2>/dev/null | grep -E 'http2|mpm_'
grep -R -n -E '^\s*Protocols' /etc/httpd /etc/apache2 2>/dev/null
# What one hop negotiates, seen from outside
curl --silent --output /dev/null --write-out '%{http_version}\n' --http2 https://your-origin.example/
```

With HTTP/2 off, browsers fall back to HTTP/1.1 by themselves, at the cost of multiplexing: more connections, and asset-heavy pages may be a little slower. Upstreams pinned to HTTP/2 do not fall back: a proxy connecting through mod_proxy_http2, gRPC, or a client hard-coded to h2c prior knowledge will simply fail, so look for that traffic before switching off. If a CDN sits in front and already speaks HTTP/1.1 to the origin, users will barely notice. Take the same care over the last steps. If the old process is still running after the restart, or `Protocols` is switched back before the package is fixed, you are back where you started.

## Notes

- In scope: 2.4.55 to 2.4.70, mod_http2 loaded, and `Protocols` enabling h2 or h2c. HTTP/1.1-only servers are not affected.
- Version string, module, `Protocols` and distribution backports are separate checks. The official httpd image has HTTP/2 off by default.
- A CDN in front does not make the origin safe. If the origin is directly reachable, what counts is what the origin itself has enabled.
- RHEL 9 and 10 have RHSAs. Debian stable and Ubuntu had no fix when checked, and standalone mod_h2 is no longer maintained.
- When mitigating, change `Protocols` globally and in every virtual host, then restart fully. A graceful restart leaves existing connections in place.
- No authoritative report of exploitation in the wild found when checked, and no KEV entry in the latest edition, but public research has demonstrated a reliable exploit.

## Further reading

- [Apache HTTP Server 2.4 vulnerabilities](https://httpd.apache.org/security/vulnerabilities_24.html): the official advisory and the primary source for affected versions and severity.
- [CHANGES_2.4.71](https://downloads.apache.org/httpd/CHANGES_2.4.71): the official changelog listing what 2.4.71 fixes.
- [Red Hat CVE-2026-119618](https://access.redhat.com/security/cve/cve-2026-119618): vendor analysis, primary for Red Hat products, with CVSS, per-product status and RHSAs.
- [Debian security tracker CVE-2026-119618](https://security-tracker.debian.org/tracker/CVE-2026-119618): Debian's own tracker, with status per release.
- [Launchpad apache2](https://launchpad.net/ubuntu/+source/apache2): Ubuntu's own package publishing record, with changelogs per release.
- [CISA Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog): the official list of vulnerabilities confirmed as exploited.
- [mod_h2 releases](https://github.com/icing/mod_h2/releases): the standalone module's own release page; the repository is archived and stops at v2.0.42.
- [Apache HTTP/2 guide](https://httpd.apache.org/docs/2.4/howto/http2.html): official configuration documentation covering `Protocols`.
- [HTTP/2 (Wikipedia)](https://en.wikipedia.org/wiki/HTTP/2): encyclopaedia entry, used only as background on h2 and h2c.

> Ideas and technical judgement by Sheng; drafted with Claude · reviewed by Codex and Grok; protocol checks run on OrbStack with httpd:2.4.70 and nginx:1.29, vulnerability not reproduced; facts checked up to 17:00 on 12 November 2026 (Taipei time)