VYPR
High severityNVD Advisory· Published Jun 15, 2026

CVE-2026-48599

CVE-2026-48599

Description

Authorization bypass in elixir-grpc HTTP transcoding allows authenticated attackers to override path-bound fields via query/body parameters.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Authorization bypass in elixir-grpc HTTP transcoding allows authenticated attackers to override path-bound fields via query/body parameters.

Vulnerability

In Elixir.GRPC.Server.Transcode.map_request/5 (lib/grpc/server/transcode.ex), all three clauses use Map.merge/2 with path bindings as the first argument, giving them the lowest merge precedence [1][2][4]. This allows query-string or request-body parameters to overwrite path-bound fields extracted by the router. The vulnerability affects grpc versions from 0.8.0 before 1.0.0 and requires HTTP-to-gRPC transcoding to be enabled [1][2].

Exploitation

An authenticated attacker can send a GET request with a query parameter that matches a path-bound field (e.g., GET /users/me/profile?user_id=victim) or a POST request with a JSON body containing the conflicting field (e.g., {"user_id": "victim"} when body: "*") [1][4]. The decoded protobuf struct handed to the handler carries the attacker-supplied value instead of the router-extracted value. No user interaction is required [1].

Impact

A successful attack allows the attacker to read or modify resources belonging to other users by bypassing authorization, multi-tenancy scoping, or ownership checks that rely on the path-bound field [1][2][4]. The CVSS v4.0 score is 7.6 (HIGH) with impacts to confidentiality and integrity [1][2].

Mitigation

The fix is implemented in commit 33b6a09 [3], which swaps the merge order so path bindings take precedence over query and body parameters. This fix is included in grpc version 1.0.0 [3][4]. Users should upgrade to 1.0.0 or later. No workaround is available, and the vulnerability is not listed on the CISA KEV [1][4].

AI Insight generated on Jun 15, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Elixir Grpc/Grpcreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: >=0.8.0 <1.0.0

Patches

1
33b6a095dbc9

fix: path params should take precedence (#541)

https://github.com/elixir-grpc/grpcPaulo ValenteJun 15, 2026via body-scan
2 files changed · +44 3
  • grpc_server/lib/grpc/server/transcode.ex+6 3 modified
    @@ -22,7 +22,8 @@ defmodule GRPC.Server.Transcode do
           ) do
         path_bindings = map_path_bindings(path_bindings)
         query = Query.decode(query_string)
    -    request = Map.merge(path_bindings, query)
    +    # Path bindings take precedence over query parameters
    +    request = Map.merge(query, path_bindings)
     
         Protobuf.JSON.from_decoded(request, req_mod)
       end
    @@ -36,7 +37,8 @@ defmodule GRPC.Server.Transcode do
           ) do
         path_bindings = map_path_bindings(path_bindings)
         body_request = map_request_body(rule, body_request)
    -    request = Map.merge(path_bindings, body_request)
    +    # Path bindings take precedence over body parameters
    +    request = Map.merge(body_request, path_bindings)
     
         Protobuf.JSON.from_decoded(request, req_mod)
       end
    @@ -51,7 +53,8 @@ defmodule GRPC.Server.Transcode do
         path_bindings = map_path_bindings(path_bindings)
         query = Query.decode(query_string)
         body_request = map_request_body(rule, body_request)
    -    request = Enum.reduce([query, body_request], path_bindings, &Map.merge(&2, &1))
    +    # Path bindings take precedence over query parameters and body parameters
    +    request = Enum.reduce([query, body_request], path_bindings, &Map.merge(&1, &2))
     
         Protobuf.JSON.from_decoded(request, req_mod)
       end
    
  • grpc_server/test/grpc/server/transcode_test.exs+38 0 modified
    @@ -48,6 +48,44 @@ defmodule GRPC.TranscodeTest do
         assert %{a: "b"} == Transcode.map_response_body(rule, request_body)
       end
     
    +  # CVE-2026-48599 / GHSA-mwr4-5g34-j5cq regression tests:
    +  # Path bindings must never be overridden by query-string or body parameters.
    +
    +  test "map_request/5 with empty body: path binding cannot be overridden by query string" do
    +    rule = %Google.Api.HttpRule{body: ""}
    +    request_body = %{}
    +    bindings = %{"latitude" => 1}
    +    qs = "latitude=999"
    +
    +    assert {:ok, %Routeguide.Point{latitude: 1}} =
    +             Transcode.map_request(rule, request_body, bindings, qs, Routeguide.Point)
    +  end
    +
    +  test "map_request/5 with body '*': path binding cannot be overridden by body" do
    +    rule = %Google.Api.HttpRule{body: "*"}
    +    request_body = %{"latitude" => 999, "longitude" => 2}
    +    bindings = %{"latitude" => 1}
    +    qs = ""
    +
    +    assert {:ok, %Routeguide.Point{latitude: 1, longitude: 2}} =
    +             Transcode.map_request(rule, request_body, bindings, qs, Routeguide.Point)
    +  end
    +
    +  test "map_request/5 with named body field: path binding cannot be overridden by query string or body" do
    +    rule = %Google.Api.HttpRule{body: "location"}
    +    request_body = %{"latitude" => 1, "longitude" => 2}
    +    bindings = %{"name" => "legitimate"}
    +
    +    assert {:ok, %Routeguide.Feature{name: "legitimate"}} =
    +             Transcode.map_request(
    +               rule,
    +               request_body,
    +               bindings,
    +               "name=attacker",
    +               Routeguide.Feature
    +             )
    +  end
    +
       test "map_route_bindings/2 should stringify the keys" do
         path_binding_atom = %{foo: "bar"}
         path_binding_string = %{foo: "bar"}
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

4

News mentions

0

No linked articles in our index yet.