Aug 26, 2026·6 min read·4 visits
An insecure Map.merge sequence in the elixir-grpc transcoding layer allows attackers to bypass tenancy controls by overriding authoritative path parameters via HTTP parameter pollution.
An authorization bypass vulnerability exists in the elixir-grpc/grpc library version 0.8.0 up to 1.0.0. Due to insecure map merging precedence inside the HTTP-to-gRPC transcoding engine, query-string parameters and request bodies can override routing path variables, allowing attackers to execute unauthorized actions on other accounts.
The Elixir gRPC library (elixir-grpc/grpc) incorporates an HTTP-to-gRPC transcoding layer within the GRPC.Server.Transcode module. This feature permits gRPC services to accept HTTP REST requests with JSON payloads and map them automatically to internal Protobuf format messages. This architectural pattern facilitates compatibility with external client applications that do not natively support standard HTTP/2-based gRPC protocols.
The vulnerability, designated as CVE-2026-48599, resides inside the parameter mapping logic of this transcoding layer. Specifically, when transcoding is enabled via the http_transcode: true option, the server processes router-extracted path variables alongside incoming query-string parameters and JSON request bodies. Due to a design flaw in the variable collection sequence, the library permits untrusted client-side inputs to overwrite authoritative route bindings.
This flaw exposes applications to HTTP Parameter Pollution (HPP) and Authorization Bypass Through User-Controlled Key (CWE-639). If an application validates user permissions against the request path but relies on the resulting gRPC struct fields for execution, an attacker can manipulate these fields to bypass authorization checks. This enables horizontal or vertical privilege escalation and unauthorized access to isolated tenant resources.
The core issue involves the evaluation order of parameter maps during the request translation process. In the Elixir programming language, the Map.merge/2 function combines two maps. If a key is present in both maps, the value from the second argument (the right-hand operand) takes precedence and overwrites the value from the first argument (the left-hand operand).
In vulnerable versions of elixir-grpc/grpc (from 0.8.0 up to, but excluding, 1.0.0), the GRPC.Server.Transcode module utilizes Map.merge/2 to combine path parameters, query-string parameters, and request body variables. The library implements three distinct clauses of the map_request/5 function to handle different configurations of the google.api.HttpRule option. In all three clauses, the merge logic incorrectly assigns the highest precedence to user-supplied inputs instead of authoritative path bindings.
When processing HTTP GET requests with an empty body, the library executes Map.merge(path_bindings, query). For POST, PUT, or PATCH requests mapping the entire request body to a catch-all asterisks parameter, it calls Map.merge(path_bindings, body_request). For mixed requests with named body fields, it reduces query-string and body maps into the path bindings map using Enum.reduce/3 with the function &Map.merge(&2, &1). In every scenario, path bindings serve as the base, allowing subsequent user-defined query parameters or body payloads to overwrite identically named keys.
To understand the mechanics of the vulnerability, we can examine the implementation within lib/grpc/server/transcode.ex. The vulnerable implementation of map_request/5 parses parameters in the following manner:
# Vulnerable implementation in lib/grpc/server/transcode.ex
def map_request(%{body: ""}, _body_request, path_bindings, query_string, req_mod) do
path_bindings = map_path_bindings(path_bindings)
query = Query.decode(query_string)
# Path bindings are passed as first parameter (overridden by query)
request = Map.merge(path_bindings, query)
Protobuf.JSON.from_decoded(request, req_mod)
endThe patch introduced in commit 33b6a095dbc91c6dee3c7b90893d7d74952e82e4 corrects the priority order by ensuring that the authoritative router-derived parameters are merged last, thereby overwriting any conflicting user-provided inputs. The remediation introduces the following changes across all three map_request/5 clauses:
# Patched implementation in lib/grpc/server/transcode.ex
def map_request(%{body: ""}, _body_request, path_bindings, query_string, req_mod) do
path_bindings = map_path_bindings(path_bindings)
query = Query.decode(query_string)
# Query parameters are passed first, ensuring path_bindings override them
request = Map.merge(query, path_bindings)
Protobuf.JSON.from_decoded(request, req_mod)
endSimilarly, for request handlers utilizing named body fields, the reduction sequence was altered from Enum.reduce([query, body_request], path_bindings, &Map.merge(&2, &1)) to Enum.reduce([query, body_request], path_bindings, &Map.merge(&1, &2)). This adjustment guarantees that the path bindings accumulator remains the overriding value at each step of the reduction.
An attack requires an environment where the transcoded endpoints extract authorization keys from path bindings. Consider a backend service providing user profile modifications at /v1/users/{user_id}/settings. A routing gateway or validation middleware verifies that the authenticated user's token matches the {user_id} segment in the HTTP request path. If this path binding is validated, the gateway forwards the request to the gRPC transcoding layer.
An attacker targeting this service attempts to modify the profile of a victim (victim_user_id). The attacker constructs an HTTP request where the path segment indicates their own validated identity (attacker_user_id), but they append a conflicting user_id inside the request body or query string.
POST /v1/users/attacker_user_id/settings HTTP/1.1
Host: vulnerable-target.local
Authorization: Bearer <attacker_token>
Content-Type: application/json
{
"user_id": "victim_user_id",
"email": "malicious@attacker-domain.com"
}Upon receiving this payload, the vulnerable server extracts path_bindings = %{"user_id" => "attacker_user_id"} and validates the token. The transcoding engine then parses the JSON body to retrieve body_request = %{"user_id" => "victim_user_id"}. Due to the insecure merge order, the resulting map contains "user_id" => "victim_user_id". The deserialized Protobuf message payload is dispatched to the backend gRPC handler, causing it to update the victim's profile and leading to account takeover.
The impact of CVE-2026-48599 is substantial, as it undermines the reliability of path-based authorization across transcoded endpoints. If an organization enforces tenant separation or access controls at the routing layer while assuming the downstream gRPC handler will process only safe parameters, the system becomes fully vulnerable to unauthorized cross-tenant operations.
The CVSS v4.0 base score is calculated as 7.6 (High) with vector string CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N. The rating is influenced by the low attack complexity and lack of user interaction requirements. Although the attack requires HTTP transcoding to be enabled, the potential consequences include high confidentiality and integrity compromise since attackers can read, overwrite, or delete sensitive data belonging to any other user inside the database.
Currently, this CVE is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and there are no reports of active exploitation in the wild. The EPSS score is recorded at 0.00273 (percentile ranking of 19.15%). However, because public proof-of-concept information is available, applications implementing vulnerable versions of elixir-grpc/grpc must be remediated immediately.
The primary remediation path is upgrading the elixir-grpc/grpc library to version 1.0.0 or higher, which includes the parameter merge priority correction. This update can be applied by adjusting the dependency list in mix.exs and executing mix deps.update grpc within the project environment.
In scenarios where immediate upgrades are blocked, teams must implement defensive validation within downstream gRPC handler functions. Developers should extract authentication credentials directly from the gRPC stream metadata or transport headers (such as x-authenticated-user-id) and cross-verify these values against the deserialized Protobuf struct fields before performing database operations.
def update_settings(request, stream) do
auth_user_id = GRPC.Stream.get_headers(stream)["x-authenticated-user-id"]
if request.user_id != auth_user_id do
raise GRPC.RPCError, status: :permission_denied, message: "Access Denied"
else
# Process the request securely
end
endAdditionally, organizations can configure API Gateways or web application firewalls (WAF) to block requests that supply query-string arguments matching restricted path variable names. This prevents malicious query pollution from reaching the Elixir runtime.
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
elixir-grpc/grpc elixir-grpc | >= 0.8.0, < 1.0.0 | 1.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 7.6 (High) |
| EPSS Score / Percentile | 0.00273 / 19.15% |
| Exploit Status | Proof-of-Concept |
| CISA KEV Status | Not Listed |
| Ransomware Use | No |
The system uses an attacker-controlled key to access a resource without verifying authorization for that resource.
CVE-2026-55637 is a high-severity DNS rebinding vulnerability affecting the genieacs-mcp Model Context Protocol server. Prior to version 0.3.2, the application's Streamable HTTP transport lacks adequate Host and Origin header validation. This omission allows external attackers to bypass the Same-Origin Policy through a victim's browser and issue unauthenticated commands to loopback listeners.
A critical vulnerability exists in the elixir-grpc library's Erlpack codec, where the unsafe deserialization of Erlang External Term Format (ETF) payloads allows unauthenticated remote attackers to cause a Denial of Service through atom table exhaustion or execute arbitrary code on the host server.
An allocation of resources without limits or throttling vulnerability exists in the Elixir grpc server component when processing unary requests. Unauthenticated remote attackers can stream unbounded data payloads, bypassing standard timeout mechanisms and exhausting host BEAM VM memory, resulting in an immediate crash of the server node.
CVE-2026-53430 is a critical uncontrolled resource consumption vulnerability in the elixir-grpc/grpc library. An unauthenticated remote attacker can cause immediate memory exhaustion and system crashes by sending crafted gRPC frames compressed with Gzip, leading to a complete Denial of Service.
A cryptographic validation flaw (CWE-345) exists in the built-in SCTP implementation of mediasoup (NPM package < 3.20.6, Rust crate < 0.22.5). Due to missing cryptographic signature verification of State Cookies, an on-path attacker targeting PlainTransport or PipeTransport without DTLS can forge state cookies containing static magic bytes. This allows the attacker to establish arbitrary SCTP associations and inject malicious DataChannel messages.
An authentication bypass and account takeover vulnerability in the AshAuthentication Elixir library (developed by team-alembic) allows unauthenticated remote attackers to compromise local accounts. By relying on mutable and unverified email claims instead of stable cryptographic issuer and subject pairings during OAuth2 and OIDC federated login flows, the application fails to validate the trust boundary of the incoming session.