Am I affected?

type your grpc_server version to check

Description

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.

Technical analysis

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.

Proof of concept

  1. Start a server that exposes a client-streaming RPC, for example RouteGuide.RecordRoute.
  2. Open an HTTP/2 connection and send HEADERS for that method with content-type: application/grpc and no grpc-timeout.
  3. Send one DATA frame with END_STREAM that holds only the 5-byte prefix 00 00 00 00 64, which declares a 100-byte message.
  4. Keep the connection open and observe that no response arrives and one BEAM scheduler stays at 100% CPU until the connection closes.

Weaknesses & attack patterns

Weakness

CWE-400 · Uncontrolled Resource Consumption in catalog → MITRE ↗
CWE-835 · Loop with Unreachable Exit Condition in catalog → MITRE ↗

Attack patterns

CAPEC-130 · Excessive Allocation MITRE ↗

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.

Affected — Hex / grpc_server Hex.pm ↗ Repository ↗

≥ 1.0.0 < 1.1.0 affected
every other version: unaffected
cpe cpe:2.3:a:elixir-grpc:grpc_server:*:*:*:*:*:*:*:*
version type semver
modules · source files · routines
modules 'Elixir.GRPC.Server.Adapters.Cowboy'
source files lib/grpc/server/adapters/cowboy.ex
routines 'Elixir.GRPC.Server.Adapters.Cowboy':reading_stream/1 · 'Elixir.GRPC.Server.Adapters.Cowboy':read_stream/1

Affected — GitHub / elixir-grpc/grpc Repository ↗

≥ 0332faa < 38955f1 affected
every other version: unaffected
cpe cpe:2.3:a:elixir-grpc:grpc_server:*:*:*:*:*:*:*:*
version type git
modules · source files · routines
modules 'Elixir.GRPC.Server.Adapters.Cowboy'
source files grpc_server/lib/grpc/server/adapters/cowboy.ex
routines 'Elixir.GRPC.Server.Adapters.Cowboy':reading_stream/1 · 'Elixir.GRPC.Server.Adapters.Cowboy':read_stream/1

Affected — Hex / grpc Hex.pm ↗ Repository ↗

≥ 0.3.1 < 1.0.0 affected
every other version: unaffected
cpe cpe:2.3:a:elixir-grpc:grpc:*:*:*:*:*:*:*:*
version type semver
modules · source files · routines
modules 'Elixir.GRPC.Server.Adapters.Cowboy'
source files lib/grpc/server/adapters/cowboy.ex
routines 'Elixir.GRPC.Server.Adapters.Cowboy':reading_stream/1 · 'Elixir.GRPC.Server.Adapters.Cowboy':read_stream/1

Affected — GitHub / elixir-grpc/grpc Repository ↗

≥ 6d8a09a < 0332faa affected
every other version: unaffected
cpe cpe:2.3:a:elixir-grpc:grpc:*:*:*:*:*:*:*:*
version type git
modules · source files · routines
modules 'Elixir.GRPC.Server.Adapters.Cowboy'
source files lib/grpc/server/adapters/cowboy.ex
routines 'Elixir.GRPC.Server.Adapters.Cowboy':reading_stream/1 · 'Elixir.GRPC.Server.Adapters.Cowboy':read_stream/1

Configurations

The server must expose at least one client-streaming or bidirectional-streaming RPC method.

References

Credits

Adam Jordan Reporter Finder
Marko Vejnovic Remediation developer
Paulo Valente Remediation reviewer
Peter Ullrich Coordinator
Jonatan Männchen / EEF Coordinator

CVSS breakdown

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
« All CVEs