Authorization Bypass Through User-Controlled Key vulnerability in elixir-grpc grpc_server and grpc allows an attacker to make a handler act on a resource other than the one named in the URL of an HTTP-transcoded route, via a request with a gRPC Content-Type.
Only the transcoding clause of GRPC.Server.do_handle_request/4 (grpc_server/lib/grpc/server.ex, and lib/grpc/server.ex before the package split) applies the route's path bindings to the request message. The Cowboy handler picks that clause from the request Content-Type, not from the route. A request to a transcoded URL with application/grpc or application/grpc-web is decoded from the body alone, so every path-bound field takes its value from the body. A gateway, proxy rule or WAF that authorizes on the URL path sees one resource while the handler receives another.
This issue affects grpc_server: from 1.0.0 before 1.1.0; grpc: from 0.8.0 before 1.0.0.
1. The header selects the clause
The Cowboy handler derives the access mode from the request Content-Type. application/json selects :http_transcoding, application/grpc selects :grpc and application/grpc-web+proto selects :grpcweb. The router still matches the transcoded URL template and extracts its path bindings.
2. Bindings are applied in one clause only
GRPC.Server.do_handle_request/4 reads the bindings with adapter.get_bindings/1 and merges them through GRPC.Server.Transcode.map_request/5 only in the :http_transcoding clause. The unary and request-streaming clauses decode the body alone with the selected codec. GRPC.Codec.Proto is in the default codecs of every server, so application/grpc is always accepted.
3. The HTTP/1.1 guard never matches
resolve_access_mode/3 has a clause that forces transcoding for HTTP/1.1 requests. It matches the version as the binary "HTTP/1.1", while Cowboy stores the version as an atom, so the clause never applies and the request works over plain HTTP/1.1.
4. Result
A request to /v1/messages/alice with Content-Type: application/grpc and a message that sets name to victim reaches the handler with name set to victim. With an empty message the field is empty: the path binding is never consulted.
http_transcode: true and a transcoded route that binds a field from the path, for example GET /v1/messages/{name}.name to victim.GET /v1/messages/alice with Content-Type: application/grpc.name set to victim, not alice.An attacker whose requests are authorized by URL path can make the handler read or modify a resource the path does not name, such as another tenant's data.
HTTP-to-gRPC transcoding must be enabled with http_transcode: true. Access to a resource must be decided from the URL path rather than from the decoded request, for example by an API gateway, proxy rule or WAF in front of the server.
{
"capec_ids": [
"CAPEC-460"
],
"cpe_ids": [
"cpe:2.3:a:elixir-grpc:grpc_server:*:*:*:*:*:*:*:*",
"cpe:2.3:a:elixir-grpc:grpc:*:*:*:*:*:*:*:*"
],
"cwe_ids": [
"CWE-436",
"CWE-639"
]
}