Aug 26, 2026·7 min read·51 visits
Unauthenticated remote attackers can crash Elixir-based gRPC servers by sending a small, highly compressed Gzip payload that expands to multiple gigabytes, triggering an Out-Of-Memory crash.
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.
The elixir-grpc/grpc library is a widely used implementation of the gRPC protocol for the Elixir programming language, running on the Erlang Virtual Machine (BEAM). In versions prior to 1.0.0, the package exposes an unauthenticated attack surface through its default handling of Gzip-compressed messages. When a gRPC service endpoint receives an incoming HTTP/2 request with the grpc-encoding: gzip header, it processes the payload using the GRPC.Compressor.Gzip module to decompress the content.
This vulnerability is classified under CWE-409: Improper Handling of Highly Compressed Data (Data Amplification), commonly known as a Gzip decompression bomb. The bug is located in the decompression phase of the gRPC message pipeline, which operates prior to length validation. Because the framework does not check the output boundaries during the decompression phase, an unauthenticated remote attacker can trigger unbounded memory allocation, crashing the target server.
The impact of this flaw is a complete and immediate Denial of Service (DoS) of the affected Elixir application node. The vulnerability does not require valid credentials, session tokens, or any specific application-state prerequisites. Any gRPC service using the default Gzip compressor component is vulnerable to this attack vector.
The root cause of CVE-2026-53430 resides in the naive implementation of the decompress/1 function in lib/grpc/compressor/gzip.ex. This function accepts an incoming binary payload and passes it directly to Erlang's :zlib.gunzip/1 function. The :zlib.gunzip/1 function is a one-shot, non-incremental wrapper around the zlib library. It allocates the memory required to decompress the entire input stream in a single blocking operation.
This design allows for a significant data amplification ratio, where repetitive sequences compress highly efficiently. For example, a payload containing consecutive zero bytes can achieve a compression ratio of approximately 1032:1 under the DEFLATE algorithm. Under these conditions, an attacker can package a compressed block of multiple gigabytes into a transport payload of a few megabytes. When the BEAM node executes :zlib.gunzip/1, it attempts to allocate a continuous segment of heap memory large enough to hold the fully expanded, uncompressed output.
Standard gRPC protective measures like max_receive_message_length fail to prevent this exploitation. The gRPC protocol engine evaluates the incoming message size limits only after the binary payload has been fully decoded and decompressed. Because the decompression process occurs within the stateful compressor layer before the framework performs the length validation, the system consumes excessive physical memory and crashes before the framework can reject the oversized message.
In the vulnerable version of the library, the decompression code was written as a direct wrapper around Erlang's zlib module:
defmodule GRPC.Compressor.Gzip do
@behaviour GRPC.Compressor
def name, do: "gzip"
def compress(data) do
:zlib.gzip(data)
end
# VULNERABLE: Direct, unbounded decompression in a single step
def decompress(data) do
:zlib.gunzip(data)
end
endThe vulnerability is mitigated by replacing this single-pass decompression with an incremental, chunk-based decompression loop. The fix, implemented in commit 1afbab9d57d2a3e16ca9c62ffa4923338ea96cfc, processes the compressed payload in recursive 8 KB chunks and monitors the cumulative decompressed output size dynamically:
defmodule GRPC.Compressor.Gzip do
@behaviour GRPC.Compressor
# Enforces a 4 MB maximum limit by default
@default_max_decompressed_size 4 * 1024 * 1024
@input_chunk_size 8_192
def decompress(data) do
max_size = Application.get_env(:grpc, :max_decompressed_message_length, @default_max_decompressed_size)
z = :zlib.open()
# Window bits value of 31 configures zlib for gzip parsing
:ok = :zlib.inflateInit(z, 31)
try do
chunks = inflate_chunks(z, data, max_size, 0, [])
:zlib.inflateEnd(z)
IO.iodata_to_binary(chunks)
after
# Ensures resource cleanup to prevent port leaks
:zlib.close(z)
end
end
defp inflate_chunks(_z, <<>>, _max_size, _acc_size, acc), do: acc
defp inflate_chunks(z, data, max_size, acc_size, acc) do
{chunk, rest} = split_chunk(data)
output = :zlib.inflate(z, chunk)
new_size = acc_size + IO.iodata_length(output)
# Dynamic size verification checks limit before inflating the next chunk
if new_size > max_size do
raise GRPC.RPCError,
status: :resource_exhausted,
message: "Decompressed message exceeds limit of #{max_size} bytes"
end
inflate_chunks(z, rest, max_size, new_size, [acc, output])
end
defp split_chunk(data) when byte_size(data) <= @input_chunk_size, do: {data, <<>>}
defp split_chunk(<<chunk::bytes-size(@input_chunk_size), rest::binary>>), do: {chunk, rest}
endBy using the stateful :zlib.inflate/2 API, the patched version guarantees that memory allocation remains bounded. If the uncompressed output exceeds the preconfigured threshold, the function raises an exception and interrupts the operation, limiting resource utilization to the specified threshold.
An attacker can exploit this vulnerability by generating a highly compressed file consisting of repeated characters, typically zero bytes. The generation of a Gzip decompression bomb can be executed with standard command-line tools:
dd if=/dev/zero bs=1M count=4096 | gzip -9 > bomb.gzipThis command produces a compressed file of approximately 4 MB that decompresses into 4 GB of data. The attacker then encapsulates this file within a standard gRPC length-prefixed frame. This frame structure requires a 1-byte compression flag set to 1, a 4-byte big-endian field denoting the compressed size, and the compressed payload itself.
To complete the attack, the adversary initiates an HTTP/2 connection to the server and transmits the payload inside an HTTP/2 DATA frame. The companion HTTP/2 HEADERS frame must contain the grpc-encoding: gzip and content-type: application/grpc headers. Once received, the Cowboy handler passes the payload directly to the decompression function, exhausting system memory and causing the node to crash.
The security impact of CVE-2026-53430 is a severe Denial of Service. Because the Erlang Virtual Machine allocates memory dynamically on the process heap, an expansion of several gigabytes of data triggers a rapid exhaustion of system RAM. When the allocation exceeds the physical memory limits of the server host or container, the operating system kernel's Out-Of-Memory (OOM) killer intervenes and terminates the entire BEAM process immediately.
This termination results in the loss of all active connections, processing queues, and state within that VM instance. In clustered configurations, the loss of a node can cause cascade failures across remaining nodes if traffic is redirected without strict rate limiting. While Kubernetes or similar orchestrators may restart the terminated container automatically, an attacker can send decompression bombs continuously to keep the service in an ongoing crash loop.
The vulnerability is assessed with a CVSS 4.0 score of 8.7. The attack is executable entirely over the network, requires no system access privileges, demands no user interaction, and has low technical complexity. The subsequent impacts on data confidentiality and integrity are ranked as none, as the bug does not allow for arbitrary code execution or unauthorized read actions.
The primary remediation strategy is upgrading the Elixir gRPC dependencies to version 1.0.0 or later. Starting with version 1.0.0-rc.1, the library has been split into individual packages. Applications running a gRPC server must replace the legacy :grpc dependency with the new :grpc_server package inside their mix.exs configuration:
def deps do
[
{:grpc_server, "~> 1.0"},
{:protobuf, "~> 0.14"}
]
endIf an immediate upgrade is not feasible, administrators can apply network-level mitigations at the API gateway or load balancer layer. For instance, reverse proxies such as Envoy or NGINX can be configured to restrict the maximum allowed size of incoming HTTP/2 request bodies. Restricting the request size to a low threshold (e.g., 1 MB) reduces the maximum payload size an attacker can transmit, mitigating the severity of the amplification ratio.
Additionally, operations teams can configure the :max_decompressed_message_length parameter in their Elixir application configuration files to fine-tune the threshold. Setting this value to match application-specific limits prevents unnecessary memory allocation:
# Set the maximum allowed decompressed payload size to 2 MB
config :grpc, max_decompressed_message_length: 2 * 1024 * 1024CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
grpc elixir-grpc | >= 0.4.0, < 1.0.0 | 1.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-409 |
| Attack Vector | Network |
| CVSS 4.0 Score | 8.7 |
| EPSS Score | 0.00348 (0.35% exploitation probability) |
| Impact | Complete Denial of Service (OOM Crash) |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
The product does not limit or properly validate the size of highly compressed input data before or during decompression, enabling a dramatic amplification of data size in memory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.
An elevation of privilege vulnerability exists in ASP.NET Core and Microsoft Visual Studio due to improper synchronization during concurrent thread execution. Authenticated remote attackers with low privileges can exploit a timing window to manipulate shared resources and assume higher-level execution contexts.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.