PT-2026-105924 · Pypi · Zapros

Published

2026-10-01

·

Updated

2026-10-01

CVSS v4.0

8.7

High

VectorAV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Impact

Denial of service via memory exhaustion. Affects all callers who streamed compressed responses relying on the chunk size — explicit (iter bytes(chunk size=...)) or the default — to bound memory. The decoder ignored that bound, so a chunk could be far larger than requested and a single compressed response could overflow memory.
python
import gzip, zapros

# Server returns ~1 GiB of zeros gzip-compressed to ~1 MiB,
# with header: Content-Encoding: gzip
bomb = gzip.compress(b"0" * 1 000 000 000) # ~1 MiB on the wire

with zapros.stream("GET", "https://malicious.example/bomb") as response:
  # Caller asks for 8 KiB chunks, expecting bounded memory:
  for chunk in response.iter bytes(chunk size=8192):
    ... # first `chunk` is ~1 GiB, not 8 KiB -> memory exhaustion

Patches

Upgrade to 0.14.0 or later. The decoders now bound the output of each decompression step to the requested chunk size: gzip/deflate via zlib's max length + unconsumed tail, brotli via output buffer limit, and zstd via a bounded stream writer. Peak memory during streaming decode is now proportional to chunk size for all supported encodings.

Workarounds

For unpatched versions:
  • Read the still-compressed body with Response.iter raw() / Response.async iter raw(), which bypass the built-in decoders, and decompress it yourself with an explicit output-size bound (e.g. zlib's max length), aborting once a configured limit is exceeded.
  • Where feasible, send Accept-Encoding: identity to disable response compression so bodies are not decompressed client-side.
  • Avoid decoding response bodies from untrusted servers.

Fix

Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

PYSEC-2026-4182

Affected Products

Zapros