Where
-Infinity
0
Severity
7

We’re publishing HTTP/2 Bomb, a remote denial-of-service exploit against most major web servers, including:

nginx

Apache httpd

Microsoft IIS

Envoy

Cloudflare Pingora

The vulnerable behavior exists in each server's default HTTP/2 configuration.

The attack was discovered by Codex, which chained two techniques known to humans for a decade: a compression bomb and a Slowloris-style hold. The bomb targets HPACK, HTTP/2's header compression scheme: one byte on the wire becomes one full header allocation on the server, repeated thousands of times per request. The hold is a zero-byte flow-control window that keeps the server from ever freeing any of it.

A curious search on Shodan revealed 880,000+ websites supporting HTTP/2 and running one of these servers, though many sit behind a CDN, which is much harder to bring down.

A home computer on a 100Mbps connection can render a vulnerable server inaccessible within seconds. Against Apache httpd and Envoy, a single client can consume and hold 32GB of server memory in roughly 20 seconds.

First published (updated )
First published (updated )
Social
reddit

an attacker could exploit this ambiguity to bypass security restrictions configured in NGINX (of have other security impacts).

Example:

GET http://foo/ HTTP/1.1 <- Used for virtual host routing     User-Agent: UA     Host: bar                <- Used for $httphost

Debian's proxyparam file used to use $httphost:

proxysetheader Host $httphost;

This has been fixed as part of Debian bug #1126960 [1].

In this case, "foo" is used for virtual host routing but the request is forwarded as:

GET / HTTP/1.1     User-Agent: UA     Host: bar     X-Real-IP: ...     X-Forwarded-For: ...     X-Forwarded-Proto: ...

If the backend application actually makes use of the Host value, this might have a security impact. For example,

if the backend application uses the Host value for tenant dispatching; logging, etc),

then this might have a security impact.

Example NGINX configuration:

server {       listen 443 ssl;       servername tenant1;       sslcertificate           /etc/nginx/ssl/tenant1.crt;       sslcertificatekey       /etc/nginx/ssl/tenant1.key;       location / {         proxypass http://backend;         include proxyparams;       }   }   server {       listen 443 ssl;       servername host2;       sslcertificate           /etc/nginx/ssl/tenant2.crt;       sslcertificatekey       /etc/nginx/ssl/tenant2.key;       location / {         allow 10.0.0.0/8;         allow 192.168.0.0/16;         allow 127.0.0.1/8;         deny all;         proxypass http://backend;         include proxyparams;       }   }

In this example, tenant2 is expected to be only available from private IP addresses. However, an attacker could target tenant2 with:

GET http://tenant1/ HTTP/1.1 <- Used for virtual host routing     User-Agent: UA     Host: tenant2                <- Used for $httphost

Another potential application, would be to send access logs of an attack to the log files of the wrong tenant.

You might be impacted if:

NGINX is directly exposed; you use $httphost (eg. through Debian's proxyparams).

NGINX's position ----------------

NGINX's position is that the bug is to use $http host. NGINX's documentation recommends using $host [2]:

proxysetheader Host $host;

I would claim that NGINX could (should?):

1. either reject host ambiguous requests altogether   (because they are attacks right?); 2. or override the HTTP header with the value from the request line.

These behaviors are consistent with what other (open-soruce) HTTP server do:

1. NGINX when using HTTP/2, HA proxy for solution 1; 2. Traefik, Caddy, Apache HTTPD for solution 2.

At the very least, the security impact of using $host vs $httphost should be better documented.

Mitigations -----------

Mitigation 1: always use $host instead of $httphost:

proxysetheader Host             $host;     proxysetheader X-Forwarded-Host $host;

Mitigation 1b: always use $servername instead of $httphost:

proxysetheader Host             $servername;     proxysetheader X-Forwarded-Host $servername; proxysetheader Host             "www.example.com";     proxysetheader X-Forwarded-Host "www.example.com"; Does not work when using ports:     if ($host != $httphost) {         return 421 "Ambiguous host";     }

# Since nginx 1.29.3:     if ($httphost != "$host$isrequestport$requestport") {         return 421 "Ambiguous host";     }

Debian info -----------

Snippet from Debian changelogs:

nginx (1.26.3-3+deb13u4) trixie; urgency=medium            d/conf/params: use "$host" instead of "$httphost" requests with a conflicting Host header) backend applications (uwsgi, fastcgi, scgi, proxy)         switch to "$host" as a safer, normalized alternative         note: this changes behaviour, as "$host" does not preserve the a port number may be affected

New proxyparams file:

# !!! Security workaround !!!     # Do not set the Host header as "$httphost".     #     # "$httphost" is the Host header exactly as supplied by the client. with a different Host header, for example:     #     #     GET https://example.com/ HTTP/1.1     #     Host: malformedhost     # behaviour.     # "$requestport", allowing Host to be constructed as:     #     $host$isrequestport$requestport     # It avoids forwarding an untrusted raw Host header to the backend.     # may therefore break or behave differently after this change.          proxysetheader Host $host;     proxysetheader X-Real-IP $remoteaddr;     proxysetheader X-Forwarded-For $proxyaddxforwardedfor;     proxysetheader X-Forwarded-Proto $scheme;

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1126960 [2] https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/ Regard,

-- Gabriel Corona

Host ambiguity could be a problem as well when using FastCGI, SCGI or uWSGI before NGINX v1.29.5. This is fixed in NGINX v1.29.5 and mitigated in Debian packages (eg. 1.26.3-3+deb13u5).

For reference, here is official NGINX fastcgiparams before v1.29.5:

fastcgiparam QUERYSTRING $querystring; fastcgiparam REQUESTMETHOD $requestmethod; fastcgiparam CONTENTTYPE $contenttype; fastcgiparam CONTENTLENGTH $contentlength;

fastcgiparam SCRIPTNAME $fastcgiscriptname; fastcgiparam REQUESTURI $requesturi; fastcgiparam DOCUMENTURI $documenturi; fastcgiparam DOCUMENTROOT $documentroot; fastcgiparam SERVERPROTOCOL $serverprotocol; fastcgiparam REQUESTSCHEME $scheme; fastcgiparam HTTPS $https ifnotempty;

fastcgiparam GATEWAYINTERFACE CGI/1.1; fastcgiparam SERVERSOFTWARE nginx/$nginxversion;

fastcgiparam REMOTEADDR $remoteaddr; fastcgiparam REMOTEPORT $remoteport; fastcgiparam REMOTEUSER $remoteuser; fastcgiparam SERVERADDR $serveraddr; fastcgiparam SERVERPORT $serverport; fastcgiparam SERVERNAME $servername;

# PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgiparam REDIRECTSTATUS 200

In this case as well, an attacker can set a HTTPHOST parameter which is not consistent with the value which was used for virtual host routing.

For the following host-ambiguous HTTP request:

GET http://foo/ HTTP/1.1 User-Agent: UA Host: bar

We have the following FastCGI variables before NGINX v1.29.5:

SERVERNAME = foo HTTPHOST = bar <- from Host header field

We have the following FastCGI variables since NGINX v1.29.5:

SERVERNAME = foo HTTPHOST = foo <- from request line

See this change: [...]

) Bugfix: fixed setting HTTPHOST when proxying to FastCGI, SCGI, and uwsgi backends.

[...]

Relevant commit:

commit 71b18973b2b5ea29ed27b47fc0e619b4df533b60 Author: Andrew Clayton <a.clayton () nginx com> Date: Sat Dec 13 07:05:27 2025 +0000

FastCGI: ensure HTTPHOST is set to the requested target host.

Previously, the HTTPHOST environment variable was constructed from the Host request header field, which doesn't work well with HTTP/2 and HTTP/3 where Host may be supplanted by the ":authority" pseudo-header field per RFC 9110, section 7.2. Also, it might give an incorrect HTTPHOST value from HTTP/1.x requests given in the absolute form, in which case the Host header must be ignored by the server, per RFC 9112, section 3.2.2.

The fix is to redefine the HTTPHOST default from a protocol-specific value given in the $host variable. This will now use the Host request header field, ":authority" pseudo-header field, or request line target URI depending on request HTTP version.

Also the CGI specification (RFC 3875, 4.1.18) notes

The server SHOULD set meta-variables specific to the protocol and scheme for the request. Interpretation of protocol-specific variables depends on the protocol version in SERVERPROTOCOL.

Closes: https://github.com/nginx/nginx/issues/256 Closes: https://github.com/nginx/nginx/issues/455 Closes: https://github.com/nginx/nginx/issues/912 Closes: https://github.com/nginx/nginx/issues/912

Similar commits exist for uWSGI and SCGI (but bot for ngxhttpproxymodule).

We can consider that the application code should rely on SERVERNAME (not HTTPHOST according) to the CGI specification [3]. However,

the usage of HTTPHOST in application code is quite prevalent as well; SERVERNAME/$servername does not really do what we want when using wildcard server names.

For example the URL reconstruction algorithm documented in WSGI [1] is:

from urllib.parse import quote url = environ['wsgi.urlscheme']+'://'

if environ.get('HTTPHOST'): url += environ['HTTPHOST'] else: url += environ['SERVERNAME']

if environ['wsgi.urlscheme'] == 'https': if environ['SERVERPORT'] != '443': url += ':' + environ['SERVERPORT'] else: if environ['SERVERPORT'] != '80': url += ':' + environ['SERVERPORT']

url += quote(environ.get('SCRIPTNAME', '')) url += quote(environ.get('PATHINFO', '')) if environ.get('QUERYSTRING'): url += '?' + environ['QUERYSTRING']

With this algorithm, HTTPHOST takes precedence over SERVERNAME. The reconstructed URL is therefore vulnerable to host ambiguity requests.

Similarly PSGI [2] says:

SERVERNAME, SERVERPORT: When combined with SCRIPTNAME and PATHINFO, these keys can be used to complete the URL. Note, however, that HTTPHOST, if present, should be used in preference to SERVERNAME for reconstructing the request URL. SERVERNAME and SERVERPORT MUST NOT be empty strings, and are always required.

Debian uses the following workaround for older versions of NGINX:

fastcgiparam HTTPHOST $host;

[1] https://peps.python.org/pep-3333/#url-reconstruction [2] https://github.com/plack/psgi-specs/blob/master/PSGI.pod [3] https://datatracker.ietf.org/doc/html/rfc3875#section-4.1.14

Regards,

-- Gabriel Corona

Errata: the subject of the original message is bogus and should instead read,

Host ambiguous requests through NGINX $httphost and Debian's proxyparams

Sorry for that,

-- Gabriel Corona

Anthropic posted a blog yesterday giving an update on their Project Glasswing efforts to find, report, and disclose vulnerabilities in a wide range of software: https://www.anthropic.com/research/glasswing-initial-update

In it, they link to their new disclosure dashboard at: https://red.anthropic.com/2026/cvd/

It currently says: "As of May 22, 2026, we've disclosed 1,596 vulnerabilities across 281 open source projects. To our knowledge, 97 of these have been patched. Of those, 88 have been assigned a Common Vulnerabilities and Exposure (CVE) record or a GitHub Security Advisory (GHSA). In other cases, maintainers have shipped a fix without publishing an advisory. The number of vulnerabilities we've disclosed is a subset of the total number of vulnerabilities that Mythos Preview has found, since the process of independent human triage and review is the rate limiting step."

In their chart below that, they clarify that in this case, "disclosed" means "reported to maintainers", not made public.

They include a list of identifiers of their reports (currently up to 1611 entries), but do not show the project name or bug type until the project has fixed the bug.

They also include lists of CVE's and GHSA's that have been published for the issues they've found. The CVE list currently includes CVE's from nginx, jq, wolfSSL, and more. The GHSA list includes libyang, mastodon, freerdp, and more.

-- -Alan Coopersmith- alan.coopersmith () oracle com Oracle Solaris Engineering - https://blogs.oracle.com/solaris

[Disclaimer: while my employer is identified in the blog post as a partner, I am not personally involved with Project Glasswing, and know nothing more about it than what has been publicly disclosed.]

https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb says: We’re publishing HTTP/2 Bomb, a remote denial-of-service exploit against most major web servers, including:

- nginx - Apache httpd - Microsoft IIS - Envoy - Cloudflare Pingora

The vulnerable behavior exists in each server's default HTTP/2 configuration. The blog tells the story of how it was found and provides technical details and PoCs.

It also says: Credits

Quang Luong for discovering the exploit. He'll be presenting his techniques at the upcoming Real World AI Security conference at Stanford in June.

Jun Rong and Duc Phan for confirming the attack on other web servers. and: Disclosure

We disclosed the issue to nginx in April. They responded by importing the maxheaders directive from freenginx, shipping it in 1.29.8 the next day: https://github.com/nginx/nginx/commit/365694160a85229a7cb006738de9260d49ff5fa2 At this point, we consider the attack public.

We disclosed to Apache on May 27, and Stefan Eissing fixed it on the same day by making cookie headers count against LimitRequestFields: https://github.com/apache/httpd/commit/47d3100b252dc6668a9e46ae885242be9eeca9cd The issue was assigned CVE-2026-49975.

The fix commits above are public and disclose the vectors directly; any capable AI model can turn those diffs into a working exploit, which is exactly how we found that Microsoft IIS, Envoy, and Pingora are also vulnerable. We've notified their maintainers. Given how short the commit-to-exploit path now is, we're releasing this writeup to provide users with the mitigations below.

Mitigations

nginx: Upgrade to 1.29.8+, which adds the maxheaders directive with a default of 1000. If you can't upgrade, disable HTTP/2 with http2 off;.

Apache httpd: The fix is in modhttp2 v2.0.41, available from the standalone modhttp2 releases and in httpd trunk but not yet in a 2.4.x release. If you can't upgrade, set Protocols http/1.1 to disable HTTP/2. Lowering LimitRequestFieldSize shrinks the per-stream blast radius (it caps the merged cookie, and so the crumb count), but it's only a partial mitigation, since an attacker can still multiply the effect across streams and connections. Lowering LimitRequestFields does nothing here: the duplicate cookie crumbs never count against it.

Microsoft IIS, Envoy, Cloudflare Pingora: No patch available at the time of writing. Disable HTTP/2 if you can, or front the server with something that enforces a hard cap on header count per request.

Generally: "Maximum decoded header size" and "maximum header count" are two different limits, and a server needs both. Any HTTP/2 termination point should cap the number of header fields per request, including cookie crumbs, independent of their total size, and should bound the lifetime of a stalled stream regardless of WINDOWUPDATE activity. And if you can't do any of that today: cap per-worker memory (cgroups, ulimit -v, container limits) tight enough that a bombed worker gets OOM-killed and respawned before it drags the box into swap. A worker process rarely needs gigabytes; letting the kernel kill one early is a better failure mode than letting the attacker hold the whole machine at 95%.

Takeaways

RFC 7541 has an entire section on this threat. §7.3 Memory Consumption opens with "an attacker can try to cause an endpoint to exhaust its memory," then explains that HPACK bounds the dynamic table via SETTINGSHEADERTABLESIZE and considers the matter handled. But when five independent implementations all read that section and still ship the same class of bug, the defect is in the spec.

The deeper miss is that the spec frames memory risk purely as an amplification ratio, and ratio is only half the equation. A 70:1 amplifier is harmless if the memory is freed when the request completes. It becomes an attack because HTTP/2 lets the client hold the connection open almost for free, pinning every allocated byte for as long as they like.

The other thing worth noting is how this exploit was found. Both halves have been public for a decade. What Codex did was read the codebases, recognize that the two compose, and build the combined attack. That combination is obvious once you see it, and yet as far as we can tell no human had put it together against these servers.

On 6/2/26 19:36, Alan Coopersmith wrote: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb says: The fix commits above are public and disclose the vectors directly; any capable AI model can turn those diffs into a working exploit, which is exactly how we found that Microsoft IIS, Envoy, and Pingora are also vulnerable. We've notified their maintainers. Given how short the commit-to-exploit path now is, we're releasing this writeup to provide users with the mitigations below. Additional patches have since been released by envoy & h2o. Posts on twitter by @califio continue to discuss whether other packages are vulnerable or not.

https://github.com/envoyproxy/envoy/security/advisories/GHSA-22m2-hvr2-xqc8 says: HTTP/2 memory exhaustion via cookie header size bypass and HPACK amplification

phlax published GHSA-22m2-hvr2-xqc8 Jun 3, 2026

Package: github.com/envoyproxy/envoy Affected versions: <1.39 Patched versions: 1.35.11 1.36.7 1.37.3 1.38.1

Summary -------

A vulnerability in Envoy's HTTP/2 downstream request processing allows an unauthenticated remote client to trigger excessive memory consumption, potentially resulting in OOM termination of the Envoy process and denial of service.

The issue arises from the combination of two behaviors:

1. Cookie header bytes are not fully accounted for during request header size validation in Envoy. 2. HPACK header block limits in oghttp2/quiche are enforced on encoded bytes without a corresponding limit on total decoded header size.

Together, these behaviors allow a malicious client to cause large decoded header allocations while bypassing the intended request header size protections.

Affected Components -------------------

Envoy HTTP/2 downstream request processing Cookie header size accounting during header validation HPACK header block size enforcement in oghttp2/quiche

Details -------

During HTTP/2 request processing, cookie header fragments are buffered separately and merged only after request header size validation has completed. Because these buffered cookie bytes are not fully included in the effective header size check, oversized cookie data can bypass maxrequestheaderskb enforcement.

Separately, oghttp2/quiche enforces header block limits on encoded HPACK bytes rather than on the fully decoded header size. A malicious client can exploit this asymmetry by using dynamic table references to keep the encoded representation relatively small while causing the decoded cookie header value to become much larger in memory.

When these behaviors are combined, a client can force Envoy to retain large per-stream allocations. Under sustained concurrency, this can rapidly increase process memory usage and lead to OOM termination.

Flow-control stalling can further increase the effectiveness of the attack by prolonging stream lifetime and delaying reclamation of per-stream memory.

Impact ------

An unauthenticated remote attacker can cause denial of service by exhausting memory in the Envoy process.

In testing against envoyproxy/envoy-google-vrp-dev:latest (v1.36.0-dev), the Envoy edge process was OOM-killed under a 3 GiB memory limit within a few seconds using a limited number of HTTP/2 connections and streams.

Additional testing showed that the attack remained effective with significantly fewer connections and streams than initially required, indicating that exploitation can be efficient even under tighter attacker-side resource constraints.

A secondary operational effect observed during testing was that oversized decoded cookies forwarded upstream could exceed the upstream service's own header limits, potentially causing upstream HTTP/2 connection resets and transient request failures.

Attack Vector -------------

A malicious downstream HTTP/2 client sends specially crafted cookie headers that combine:

incomplete cookie-size accounting during request validation; and HPACK decoded-size amplification via small encoded representations.

The impact can be amplified further by using HTTP/2 flow-control behavior to extend stream lifetime and delay memory reclamation.

Patches -------

A complete fix requires addressing both contributing issues:

include buffered cookie bytes in request header size accounting before request acceptance; and enforce limits on decoded header size, not only on encoded HPACK block size.

Fixing only one side may reduce exploitability but does not fully address the underlying issue.

Workarounds -----------

No complete workaround is known short of applying a fix.

Possible temporary mitigations include:

disabling downstream HTTP/2 where operationally feasible; enforcing stricter request header and cookie limits before traffic reaches Envoy; and monitoring Envoy memory usage for abnormal growth under HTTP/2 traffic.

Detection ---------

Potential indicators of exploitation include:

rapid or sustained abnormal memory growth in the Envoy process; OOM termination, including exit status 137 in containerized environments; and unusual HTTP/2 traffic patterns involving repeated indexed cookie references.

Credits ------- Credit: Ryoga Yamashita.

Severity: High, 7.5 / 10 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVE ID: CVE-2026-47774 https://github.com/h2o/h2o/security/advisories/GHSA-qcrr-wrhc-pgq9 says: HTTP/2 state amplification

kazuho published GHSA-qcrr-wrhc-pgq9 Jun 3, 2026

Package: h2o Affected versions: commits up to 8dc37cb Patched versions: 9265bdd and above

Impact ------

Recently, an attack against HTTP/2 servers was published that combines state amplification caused by HPACK decompression with Slowloris-style stream stalling: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb.

H2O reduces HPACK state amplification by representing HTTP header names and values internally as references where possible. However, in light of this attack, additional limits may be needed, depending on the configuration, to bound decoded header state and prevent amplified state from being retained by stalled HTTP/2 streams.

Patches ------- Mitigations were added in #3597 and landed on master as 9265bdd: https://github.com/h2o/h2o/pull/3597 https://github.com/h2o/h2o/commit/9265bdd9a996ed992681055e3996baf3e09d2063

References ---------- https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb

Severity: High, 7.5 / 10 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVE ID: No known CVE -- -Alan Coopersmith- alan.coopersmith () oracle com Oracle Solaris Engineering - https://blogs.oracle.com/solaris

Red Hat OpenShift Data Foundation 4.14.33 security, enhancement & bug fix updateFIXED BUGS:==========DFBUGS-6993: RHODF 4.14.33 releaseNGINX: Arbitrary Code Execution Vulnerability (CVE-2026-42945)

First published (updated )

This vulnerability allows remote attackers to execute arbitrary code on affected installations of NGINX. Authentication is not required to exploit this vulnerability. The ZDI has assigned a CVSS rating of 8.1. The following CVEs are assigned: CVE-2026-27654.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203