Loop with Unreachable Exit Condition ('Infinite Loop') vulnerability in elixir-grpc grpc_server and grpc allows unauthenticated attackers to occupy a BEAM scheduler indefinitely via a client-streaming or bidirectional-streaming request whose body ends inside a gRPC message.
GRPC.Server.Adapters.Cowboy.read_stream/1 (grpc_server/lib/grpc/server/adapters/cowboy.ex, and the Cowboy adapter in grpc before the package split) asks for more data whenever the buffer does not hold a complete message. Once the request body has ended, every further read returns an empty chunk, so the buffer never changes and the function retries without end. A single 5-byte length prefix sent with END_STREAM keeps one scheduler busy for as long as the connection stays open, and repeated requests exhaust all schedulers.
This issue affects grpc_server: from 1.0.0 before 1.1.0; grpc: from 0.3.1 before 1.0.0.
1. A partial message
A client sends a 5-byte gRPC length prefix that declares more bytes than follow it, and ends the request body with END_STREAM.
2. The reader asks for more
read_stream/1 calls GRPC.Message.get_message/1, which returns false because the declared message is incomplete. read_stream/1 then sets need_more and reads again through Handler.read_body/1.
3. Every read is empty
Once the body has been read, the handler's async_read_body/2 (and cowboy_req:read_body/2 in older releases) returns an empty chunk at once. The buffer stays the same, the exit clause for an empty finished buffer never matches, and the loop repeats.
4. No timeout ends it
Each iteration is a message round trip between two local processes, not a socket wait, so no I/O timeout applies. Without a grpc-timeout header there is no deadline, and the adapter's idle timeout defaults to :infinity. One scheduler stays at full load until the client closes the connection.
RouteGuide.RecordRoute.HEADERS for that method with content-type: application/grpc and no grpc-timeout.DATA frame with END_STREAM that holds only the 5-byte prefix 00 00 00 00 64, which declares a 100-byte message.An unauthenticated client can keep one scheduler busy per open connection with a 5-byte request, and enough connections deny service to every application on the node.
The server must expose at least one client-streaming or bidirectional-streaming RPC method.
{
"capec_ids": [
"CAPEC-130"
],
"cpe_ids": [
"cpe:2.3:a:elixir-grpc:grpc_server:*:*:*:*:*:*:*:*",
"cpe:2.3:a:elixir-grpc:grpc:*:*:*:*:*:*:*:*"
],
"cwe_ids": [
"CWE-400",
"CWE-835"
]
}