#!/bin/bash # CVE-2026-119618 (mod_http2 assign_headers heap corruption, httpd 2.4.55-2.4.70) # 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 certificates # come from the edge, not mod_md. So the modules are removed from every # Alma-based Apache image and this gate fails the build if they ever come back. # # httpd-h2-md-gate.sh remove uninstall mod_http2 / mod_md RPMs (if present) # httpd-h2-md-gate.sh check fail unless the modules cannot load, `httpd -t` # passes, and record the httpd version # # Both are idempotent and safe on images with no Apache at all (a no-op). set -euo pipefail BAD_MODULES='http2_module|proxy_http2_module|md_module' MOD_PKGS='mod_http2 mod_md' cmd_remove() { local p present=() for p in $MOD_PKGS; do rpm -q "$p" >/dev/null 2>&1 && present+=("$p") done if [ "${#present[@]}" -gt 0 ]; then dnf remove -y "${present[@]}" fi # Belt and braces if a package was removed but a module file was left behind. rm -f /etc/httpd/conf.modules.d/10-h2.conf /etc/httpd/conf.modules.d/10-proxy_h2.conf \ /etc/httpd/conf.modules.d/*-md.conf \ /usr/lib64/httpd/modules/mod_http2.so /usr/lib64/httpd/modules/mod_proxy_http2.so \ /usr/lib64/httpd/modules/mod_md.so } cmd_check() { local p mods v fail=0 command -v httpd >/dev/null 2>&1 || { echo "gate: no httpd binary" >&2; exit 1; } for p in $MOD_PKGS; do if rpm -q "$p" >/dev/null 2>&1; then echo "gate FAIL: RPM $p is installed" >&2; fail=1; fi done # Anchored on the module name column ("systemd_module" must NOT match md_module). mods=$(httpd -M 2>/dev/null) || { echo "gate FAIL: httpd -M failed" >&2; exit 1; } if printf '%s\n' "$mods" | grep -E "^ (${BAD_MODULES}) "; then echo "gate FAIL: HTTP/2 or mod_md module still loadable" >&2; fail=1 fi [ "$fail" -eq 0 ] || exit 1 httpd -t v=$(rpm -q --qf '%{VERSION}-%{RELEASE}' httpd-core) printf '%s\n' "$v" > /etc/whp-httpd-version echo "gate OK: httpd-core ${v}; no http2/proxy_http2/md modules; httpd -t passes" } case "${1:-}" in remove) cmd_remove ;; check) cmd_check ;; *) echo "usage: $0 remove|check" >&2; exit 2 ;; esac