Remove mod_http2/mod_md from Apache images + build gate (CVE-2026-119618) #39

Merged
jknapp merged 1 commits from fix/disable-http2-md-modules into trunk 2026-11-12 14:01:07 +00:00
Owner

Why

CVE-2026-119618 (CRITICAL): Apache mod_http2 assign_headers() heap corruption -> RCE, httpd 2.4.55-2.4.70, fixed upstream in 2.4.71. AlmaLinux has no fixed httpd yet (EL10 httpd-2.4.63-13.el10_2.8 has no fix), so rebuilding cannot remove the code. Our default config already does not negotiate h2 (no Protocols directive), this makes it structurally impossible (defense in depth). Nothing in WHP needs HTTP/2 or mod_md inside a container: the HAProxy edge terminates h2/h3 and speaks HTTP/1.1 to backends, and Let's Encrypt is done by the edge. (Also fixes the CVE-2026-106023 mod_md crash surface: mod_md is not installed on EL10 at all.)

Changes

  • scripts/httpd-h2-md-gate.sh (new): remove uninstalls the mod_http2 / mod_md RPMs if present (mod_http2 is a separate package, nothing requires it; dnf remove --assumeno showed it removes only that 1 package and keeps httpd). check fails the build if rpm -q mod_http2|mod_md succeeds, httpd -M lists http2_module/proxy_http2_module/md_module (anchored, so systemd_module does not match), or httpd -t fails; writes /etc/whp-httpd-version.
  • Dockerfile (cac php82-85, also form-sender base), Dockerfile.shared-httpd, Dockerfile.fpm: final RUN gate remove && gate check (after all package steps) and LABEL org.whp.httpd-h2-md="removed". cac-fpm only has httpd-core (no mod_http2) so it is gate-only.
  • Removed files (via the RPM): /etc/httpd/conf.modules.d/10-h2.conf, 10-proxy_h2.conf, mod_http2.so, mod_proxy_http2.so.
  • .gitea/workflows/build-push.yaml: gate script added to the shellcheck list.
  • Audit: httpd version per image = docker run --rm --entrypoint cat IMG /etc/whp-httpd-version (a LABEL cannot hold a value computed in a RUN; the static label marks hardened images).
  • No http2/Protocols/MDomain/h2:// reference exists in this repo's configs/scripts; none in the WHP repo's Apache templates (only the Go panel's own HTTP/2 server and docs).

Verified locally (amd64; arm64 build of shared-httpd also passes, gate OK under qemu)

cac php85, shared-httpd, cac-fpm php83 built; gate OK in each; httpd -M has none of the 3 modules, httpd -t Syntax OK; HTTP/1.1 requests served (cac: 200 over https/1.1 with --http2 negotiating 1.1); h2c prior-knowledge fails; shared-httpd listens :80/:443 and behaves identically to the current image. Negative test: gate run against the current published cac:php83 exits 1.
NOT verified: the real CI run, the pkg-cache path, cac-litespeed/OLS images (not Apache, untouched).

IMPORTANT: merging triggers a full rebuild

build-push.yaml runs on push to trunk and publishes the whole matrix (cac, cac-fpm, litespeed, shared-httpd, ...). That is intended (all images refreshed). Pushing this branch does not publish anything.
Before merging, record rollback digests for every tag:

for i in cac:php82 cac:php83 cac:php84 cac:php85 cac:latest cac-fpm:php82 cac-fpm:php83 cac-fpm:php84 cac-fpm:php85 cac-fpm:latest shared-httpd:latest; do echo "$i $(docker buildx imagetools inspect repo.anhonesthost.net/cloud-hosting-platform/$i --format '{{.Manifest.Digest}}')"; done

After merge verify: every Build job green; on a canary pull, httpd -M | grep -E '^ (http2|proxy_http2|md)_module' empty, cat /etc/whp-httpd-version, sites load (test server first), then roll fleet. Rollback = retag the recorded digest. Rebuild again when Alma ships httpd 2.4.71 (module removal can stay).

🤖 Generated with Claude Code

https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb

## Why CVE-2026-119618 (CRITICAL): Apache mod_http2 `assign_headers()` heap corruption -> RCE, httpd 2.4.55-2.4.70, fixed upstream in 2.4.71. AlmaLinux has no fixed httpd yet (EL10 httpd-2.4.63-13.el10_2.8 has no fix), so rebuilding cannot remove the code. Our default config already does not negotiate h2 (no `Protocols` directive), this makes it structurally impossible (defense in depth). Nothing in WHP needs HTTP/2 or mod_md inside a container: the HAProxy edge terminates h2/h3 and speaks HTTP/1.1 to backends, and Let's Encrypt is done by the edge. (Also fixes the CVE-2026-106023 mod_md crash surface: mod_md is not installed on EL10 at all.) ## Changes - `scripts/httpd-h2-md-gate.sh` (new): `remove` uninstalls the `mod_http2` / `mod_md` RPMs if present (`mod_http2` is a separate package, nothing requires it; `dnf remove --assumeno` showed it removes only that 1 package and keeps httpd). `check` fails the build if `rpm -q mod_http2|mod_md` succeeds, `httpd -M` lists `http2_module`/`proxy_http2_module`/`md_module` (anchored, so `systemd_module` does not match), or `httpd -t` fails; writes `/etc/whp-httpd-version`. - `Dockerfile` (cac php82-85, also form-sender base), `Dockerfile.shared-httpd`, `Dockerfile.fpm`: final `RUN gate remove && gate check` (after all package steps) and `LABEL org.whp.httpd-h2-md="removed"`. cac-fpm only has httpd-core (no mod_http2) so it is gate-only. - Removed files (via the RPM): `/etc/httpd/conf.modules.d/10-h2.conf`, `10-proxy_h2.conf`, `mod_http2.so`, `mod_proxy_http2.so`. - `.gitea/workflows/build-push.yaml`: gate script added to the shellcheck list. - Audit: httpd version per image = `docker run --rm --entrypoint cat IMG /etc/whp-httpd-version` (a LABEL cannot hold a value computed in a RUN; the static label marks hardened images). - No http2/`Protocols`/`MDomain`/`h2://` reference exists in this repo's configs/scripts; none in the WHP repo's Apache templates (only the Go panel's own HTTP/2 server and docs). ## Verified locally (amd64; arm64 build of shared-httpd also passes, gate OK under qemu) cac php85, shared-httpd, cac-fpm php83 built; gate OK in each; `httpd -M` has none of the 3 modules, `httpd -t` Syntax OK; HTTP/1.1 requests served (cac: 200 over https/1.1 with `--http2` negotiating 1.1); h2c prior-knowledge fails; shared-httpd listens :80/:443 and behaves identically to the current image. Negative test: gate run against the current published `cac:php83` exits 1. NOT verified: the real CI run, the pkg-cache path, `cac-litespeed`/OLS images (not Apache, untouched). ## IMPORTANT: merging triggers a full rebuild `build-push.yaml` runs on push to `trunk` and publishes the whole matrix (cac, cac-fpm, litespeed, shared-httpd, ...). That is intended (all images refreshed). Pushing this branch does not publish anything. Before merging, record rollback digests for every tag: ``` for i in cac:php82 cac:php83 cac:php84 cac:php85 cac:latest cac-fpm:php82 cac-fpm:php83 cac-fpm:php84 cac-fpm:php85 cac-fpm:latest shared-httpd:latest; do echo "$i $(docker buildx imagetools inspect repo.anhonesthost.net/cloud-hosting-platform/$i --format '{{.Manifest.Digest}}')"; done ``` After merge verify: every Build job green; on a canary pull, `httpd -M | grep -E '^ (http2|proxy_http2|md)_module'` empty, `cat /etc/whp-httpd-version`, sites load (test server first), then roll fleet. Rollback = retag the recorded digest. Rebuild again when Alma ships httpd 2.4.71 (module removal can stay). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
jknapp added 1 commit 2026-11-12 13:59:19 +00:00
mod_http2 (httpd 2.4.55-2.4.70) assign_headers() heap corruption -> RCE;
AlmaLinux has no fixed httpd yet. Nothing in WHP uses HTTP/2 inside a
container (HAProxy edge terminates h2/h3 and speaks HTTP/1.1 to backends),
so uninstall mod_http2 (and mod_md if ever present) from cac, cac-fpm and
shared-httpd. scripts/httpd-h2-md-gate.sh fails the build if http2_module,
proxy_http2_module or md_module is loadable or `httpd -t` fails, writes
/etc/whp-httpd-version and the images get LABEL org.whp.httpd-h2-md=removed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185ukXjXyosSkunDsdWz3mb
jknapp merged commit 1c9b0edeca into trunk 2026-11-12 14:01:07 +00:00
jknapp deleted branch fix/disable-http2-md-modules 2026-11-12 14:01:07 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cloud-hosting-platform/cloud-apache-container#39