CVE-2026-84304: gRPC-Go Heap Memory Exhaustion via HTTP/2 DATA Frame Fragmentation
Any unauthenticated attacker can crash a gRPC-Go server by sending a large number of tiny HTTP/2 DATA frames across multiple streams, consuming far more heap memory than the actual payload size would…

The problem
In gRPC-Go <= 1.83.0, internal/transport/transport.go stores every incoming HTTP/2 DATA frame as its own recvMsg entry in recvBuffer, regardless of frame size. Each entry carries fixed-size metadata and allocation overhead on top of the actual byte payload.
An attacker who fragments a stream payload into millions of 1-byte DATA frames forces the server to allocate millions of those tracking structures. Multiplexing several such streams concurrently can exhaust the Go runtime heap, triggering an out-of-memory panic and a remote denial of service.
No authentication is required.
Proof of concept
A working proof-of-concept for CVE-2026-84304 in google.golang.org/grpc, with the exact payload below.
# Open N concurrent gRPC streams to the target server.
# On each stream, send the request body as millions of individual
# 1-byte HTTP/2 DATA frames instead of one normal-sized frame.
# The total byte volume stays within flow-control limits (e.g. 65535 bytes),
# so the server never applies backpressure -- yet each frame costs a
# full recvMsg allocation on the heap.
#
# Conceptual HTTP/2 frame sequence per stream (repeated ~65535 times):
#
# DATA frame (stream_id=N, length=1, flags=0x00) <1 byte payload>
# DATA frame (stream_id=N, length=1, flags=0x00) <1 byte payload>
# ... (repeat until heap exhausted)
# DATA frame (stream_id=N, length=1, flags=0x01) END_STREAM
#
# Raw HTTP/2 binary layout of a single 1-byte DATA frame:
# +--------+--------+--------+--------+--------+--------+--------+--------+--------+
# | Length (3 bytes) = 0x000001 | Type=DATA(0x00) | Flags=0x00 |
# +--------+--------+--------+--------+--------+--------+--------+--------+--------+
# | Stream Identifier (31 bits, e.g. 0x00000001) |
# +--------+--------+--------+--------+--------+--------+--------+--------+--------+
# | Data (1 byte) |
# +------------------+
#
# Hex bytes for one such frame:
00 00 01 # Length = 1
00 # Type = DATA
00 # Flags = none
00 00 00 01 # Stream ID = 1
AA # 1-byte payload
#
# Repeat this frame millions of times across multiple concurrent streams.The root cause is that recvBuffer in internal/transport/transport.go allocates a new recvMsg struct for every DATA frame received, no matter how small. HTTP/2 flow control only caps the total bytes in flight, not the number of frames, so an attacker can legally send millions of frames before the window closes.
The patch (PR #9331, commit 7354d9c; backported in PR #9333, commit 8cfeca0) adds receive-buffer compaction: once the ratio of per-frame overhead to actual payload data becomes excessive, consecutive small buffers are coalesced into a single larger buffer drawn from a shared pool.
This collapses millions of 1-byte recvMsg entries into far fewer pooled allocations, eliminating the amplification. The feature is on by default and can be temporarily disabled with GRPC_GO_EXPERIMENTAL_ENABLE_RECEIVE_BUFFER_COMPACTION=false.
CWE-400 (Uncontrolled Resource Consumption): the server had no bound on the number of frame-level allocations independent of flow-control byte limits.
The fix
Upgrade to google.golang.org/grpc v1.83.1 or later. The fix is included in commit 7354d9c8 (master) and commit 8cfeca0e (v1.83.x backport). No code changes are required after upgrading; receive-buffer compaction is enabled by default. If the new behavior causes regressions, set the environment variable GRPC_GO_EXPERIMENTAL_ENABLE_RECEIVE_BUFFER_COMPACTION=false as a temporary escape hatch (this variable will be removed in a future release).
Related research
- highgRPC-Go: xDS RBAC Authorization Bypass, HTTP/2 Rapid Reset DoS, and NOT-Rule Panic
- high · 8.5CVE-2026-55108CVE-2026-55108: KubeVela Terraform Remote Loader Symlink DoS
- highCVE-2026-77354CVE-2026-77354: kin-openapi Uncontrolled Memory Allocation via deepObject Query Parameter
- high · 7.5CVE-2026-64868CVE-2026-64868: new-api Unauthenticated Webhook DoS via Unbounded Body Read