Servers, proxies and network services

HAProxy: CVE-2026-110353 truncated HTTP/2 PING frame

HAProxy HTTP/2 PING check

HAProxy's HTTP/2 code does not treat a truncated PING frame as a short read (CVE-2026-110353). A PING frame cannot be used until it is complete, but its presence still wakes the connection up, so the worker thread never goes back to idle. A remote client with no login can open a connection, keep a partial PING frame pending and hold a thread at 100% CPU for as long as the connection stays open or until timeout http-request runs out. The vendor rates the impact as moderate, because it depends on how many of your connections look like this.

CVE CVE-2026-110353 (denial of service in h2c_handle_ping in src/mux_h2.c), published 22 October 2026
Severity High 7.5
Affected 3.1.x (end of life), 3.2.x before 3.2.26, 3.3.x before 3.3.17, 3.4.x before 3.4.7. 3.0 and older are outside this CVE's range (but see the Red Hat advisories below: Red Hat shipped an advisory for its 3.0 build)
Fixed 3.4.7, 3.3.17 and 3.2.26, all released 14 October 2026
Vendor workaround Set timeout http-request to a low value such as 1 to 5 seconds. It limits CPU consumption, it does not fix the bug
Second flaw The same releases fix a CPU-exhaustion flaw in the HTTP/1 parser (a chunked request with a chunk-size line longer than the buffer). The vendor does not state its affected range, so this tool does not rule out any HTTP-mode HAProxy because of it

The CVE text and the vendor disagree, and this tool follows the vendor. The CVE description says "3.2 before 3.4.6". HAProxy's own release notes say the short-read handling was fixed in 2.5 but PING was missed. They say it only became a problem in 3.1, when the wake-up logic changed, and that the fixes shipped in 3.4.7, 3.3.17 and 3.2.26. So 3.4.6 is not fixed, whatever the CVE description implies.

Quick start

  1. Download the script. The repository is mirrored on GitHub and Codeberg; pick a base URL.

    # BASE from GitHub:   https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main
    # BASE from Codeberg: https://codeberg.org/PrivacySafe/security-patches/raw/branch/main
    # curl -fLO "$BASE/haproxy/haproxy-check.sh"
    curl -fLO https://raw.githubusercontent.com/PrivacySafe/security-patches/refs/heads/main/haproxy/haproxy-check.sh
    
  2. Read it before running it, then make it executable.

    less haproxy-check.sh
    chmod +x haproxy-check.sh
    
  3. Check this host. The script finds HAProxy on PATH, in the usual locations and from running processes, and reads the configuration files the running process was started with. To check a specific binary, pass its path.

    ./haproxy-check.sh check
    ./haproxy-check.sh check /opt/haproxy/sbin/haproxy
    

Commands

Command What it does
check [BINARY ...] (default) Reads the version from haproxy -v, applies the vendor's ranges, checks whether the running processes use a binary that was replaced on disk, and reads the configuration for HTTP/2 reachability and the timeout http-request value
mitigate [--timeout N] [--disable-h2-upgrade] [--dry-run] [--reload] [--force] Changes the host (root). Applies the vendor's workaround: adds timeout http-request 5s (or N, 1 to 60) to every defaults section that has no such line, and never changes a value you set. --disable-h2-upgrade also adds option disable-h2-upgrade (PrivacySafe recommendation). It runs haproxy -c before and after, copies every file first, and puts the originals back at once if HAProxy rejects the result. Nothing is reloaded unless you add --reload (a graceful reload). It does nothing on a version outside the affected range (3.1 to 3.4 before the fixed releases) unless you add --force
rollback [--dry-run] [--reload] Puts back every file mitigate changed
version Prints the script version

Environment: HAPROXY_CFG (space-separated files or directories) replaces configuration discovery. STATE_DIR (default /var/lib/psf-security-patches/haproxy) holds the backups and the manifest that rollback reads.

Exit codes: 0 nothing exposed, 1 an affected version is exposed, its configuration could not be read, or it is on the unfixable 3.1 branch, 2 bad arguments.

Commands that change the host need root. Run them with sudo from an admin account, not from a root login, so the change is recorded against a person. The script stops and prints the exact command if you forget:

sudo ./haproxy-check.sh mitigate --dry-run
sudo ./haproxy-check.sh mitigate
sudo ./haproxy-check.sh rollback

How HTTP/2 becomes reachable, which decides exposure

  • TLS listeners offer HTTP/2 only when the bind line has alpn h2. proto h2 on a bind line forces HTTP/2.
  • Clear-text HTTP listeners accept the HTTP/2 preface by default and upgrade the connection, unless the frontend has option disable-h2-upgrade. So a plain bind :80 in mode http is reachable over HTTP/2 even though no configuration line says h2. This is easy to miss, and the script does not treat "no explicit h2" as safe.
  • alpn h2 on a backend server line is HAProxy talking HTTP/2 to your servers. It does not expose the frontend, and the script ignores it.
  • Comments are ignored.
  • mode tcp only: the HTTP/2 multiplexer is not in use, so the script reports no exposure.

The exposure test is a text search of the configuration, not a parse of the live configuration. If HAProxy is built from many included files or generated at runtime, check haproxy -c -f output and the running configuration yourself.

How to read the result

  • Affected and exposed: upgrade to 3.2.26, 3.3.17 or 3.4.7 or later, then reload.
  • Affected but no HTTP/2 path found: exit 0. If mode http is in use, the script still says the HTTP/1 flaw fixed in the same releases may be reachable, so upgrade anyway.
  • 3.1.x: always exit 1. The branch is end of life: move to a supported branch.
  • Development builds (3.5-dev) cannot be judged by version. The script asks you to check that the build includes the "properly handle short reads on PING frames" change.
  • Distribution packages backport fixes without changing the version. The script reads the package changelog for a mention of the CVE.
  • A reload keeps the old binary running in some setups. If a process runs a binary that was replaced on disk, the script says so.

Fixing it

Upgrade to 3.2.26, 3.3.17 or 3.4.7 or later and reload. Until then, apply the vendor's workaround for the PING flaw with ./haproxy-check.sh mitigate --dry-run and then ./haproxy-check.sh mitigate --reload. It limits CPU use while a partial PING frame is pending. It does not fix the bug, and it does not change a timeout http-request you already set. If you do not need clear-text HTTP/2, adding option disable-h2-upgrade to HTTP frontends and removing h2 from alpn lists takes the multiplexer out of reach. That last step is PrivacySafe's recommendation.

Verified on HAProxy 3.1.0, 3.2.0 and 3.4.0 built from source, each with a clear-text listener. The check flagged each one (3.1 as end of life) and haproxy -c accepted both added lines. A half-sent request stayed open for the full six seconds before the change and got a 408 after two seconds with timeout http-request 2s. rollback restored the file exactly and the old behavior.

Sources

Before you run it

  • The fix. Update to 3.4.7, 3.3.17 or 3.2.26. Branch 3.1 is end of life: move to a supported branch.
  • Two sources disagree and the script follows the vendor. The CVE description says "3.2 before 3.4.6", but HAProxy's release notes say the bug was introduced in 3.1 and that 3.4.6 is not fixed. HAProxy 3.0 and older are outside this CVE's range.
  • Development builds are not judged. For a 3.5 development build, check the commit yourself.
  • The impact is a denial of service. A client holding a partial PING frame can keep a worker thread at full CPU until the connection ends or timeout http-request expires. There is no hunt.
  • It also checks running docker and podman containers, unless you name a directory or set SCAN_CONTAINERS=0. A read-only probe inside each running docker and podman container captures the output of haproxy -v and the configuration files (with password values and auth user:pass credentials redacted inside the container before they are copied) into a private temporary directory. The script then runs once per container, in isolation, against that copy, so one container's configuration never changes another's result. Each container is judged by its own configuration only. The copies are removed on exit. A path shown as .../docker_NAME/... is inside the container NAME. It is skipped when you name a binary or directory yourself.

Red Hat advisories

Red Hat's advisory list (security advisories released 2026-04-01 to 2026-11-03) names the CVEs below. A Red Hat build is judged by its RPM release, not by the upstream version number, because Red Hat backports fixes: the advisory names the release that fixes it. A CVE with no advisory in the list has none for that period, which is not the same as not affected. The current state is on Red Hat's CVE database.

The only advisory is for a 3.0 build, although HAProxy gives 3.1 as the first affected line: check says so for a 3.0 build that is a Red Hat one.

Advisory Released Severity Package and stream CVEs on this page
RHSA-2026:83844 2026-10-16 Important haproxy-3.0.30-0.1.hum1 (Hummingbird) CVE-2026-110353

The Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.

Edit this page on Codeberg

The PrivacySafe Ecosystem

Shop at Ivy Cyber

Ivy Cyber offers PrivacySafe products and services in the USA and has partnerships with 3NSoft in Canada and Kuip Limited in the European Union. Enterprise services and consulting are available at ivycyber.com

PrivacySafe Foundation is a 501(c)(3) nonprofit public charity that supports the development of the PrivacySafe applications, along with the components they rely upon: 3NWeb protocols, filesystem, documentation, and reference implementations.

PrivacySafe Foundation

Donations to PrivacySafe Foundation support education, research, documentation, and public code. Purchases from Ivy Cyber support PrivacySafe products, services, hosting, and technical support. Together, we're building a better web.