Vulnerability EEF-CVE-2026-71397
Summary
Unbounded request body accumulation on streaming RPCs causes memory exhaustion in grpc_server
Details
Summary
Allocation of Resources Without Limits or Throttling vulnerability in elixir-grpc grpc_server allows unauthenticated attackers to exhaust memory and crash the node via an oversized client-streaming or bidirectional-streaming request body.
The streaming read clause of 'Elixir.GRPC.Server.Adapters.Cowboy.Handler':info/3 (grpc_server/lib/grpc/server/adapters/cowboy/handler.ex) never checks the configured max_body_size. Only the unary read path enforces that cap. 'Elixir.GRPC.Server.Adapters.Cowboy':reading_stream/1 (grpc_server/lib/grpc/server/adapters/cowboy.ex) appends every received chunk to its buffer until a complete length-prefixed message arrives. A client can declare a very large message and send it across many small HTTP/2 DATA frames, and the server buffers all of it.
This issue affects grpc_server: from 1.0.0 before 1.0.6.
Details
1. The cap applies to unary reads only
The commit that added max_body_size checks it in read_full_body/4, which serves unary requests through the {:read_full_body, ref, pid} clause of 'Elixir.GRPC.Server.Adapters.Cowboy.Handler':info/3. The {:read_body, ref, pid} clause, which serves streaming requests, returns each chunk to the caller with no size check.
2. Unbounded buffering
'Elixir.GRPC.Server.Adapters.Cowboy':reading_stream/1 reads chunks through that clause and appends each one to a binary buffer. It emits a message only when GRPC.Message.get_message/1 finds a complete length-prefixed gRPC message in the buffer. Until then, the buffer grows with every chunk.
3. Memory exhaustion
A client that declares a large message length and keeps sending DATA frames without END_STREAM makes the buffer grow without limit. The BEAM eventually runs out of memory and the node crashes.
Proof of concept
- Start a
grpc_serverendpoint that exposes a client-streaming or bidirectional-streaming RPC method. - Open an HTTP/2 connection and send a request to that method.
- Send the request body across many small HTTP/2 DATA frames without
END_STREAM, well past the configuredmax_body_size. - Observe that the server buffers all of it and server memory grows. The equivalent unary call is rejected with
RESOURCE_EXHAUSTED.
Impact
An unauthenticated client can crash a grpc_server node through one streaming RPC connection. This takes down every service on that node.
Configurations
The server must expose at least one client-streaming or bidirectional-streaming RPC method.