GitHub Advisoryadvisory · PyPI

GHSA-5vjj-2r48-q622 Zapros has an Unbounded Content-Encoding decompression chain that allows denial of service

MEDIUM Published 2026-09-23 Modified 2026-09-23 Official page ↗
Aliases
CVE-2026-61541
Ecosystem
PyPI
Packages
zapros
Severity
Moderate
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Weaknesses
CWE-770
Reviewed
2026-09-23

Affected packages

• PyPI zapros: < 0.14.0 → fixed in 0.14.0

Description

Impact Who is impacted: • Any application using Zapros to make HTTP requests to untrusted servers • Applications that follow redirects to attacker-controlled hosts Attack vector: • A malicious HTTP server returns a response with many chained content encodings. When the client attempts to decode, it creates a deeply nested decompression chain consuming excessive resources. Patches Fixed in version 0.14.0. The fix adds a hardcoded limit of 5 `Content-Encoding` layers. Responses exceeding this limit raise `DecodingError`. Workarounds Add middleware that checks for a malicious Content-Encoding header. ```python from typing import cast from zapros import ( AsyncBaseHandler, AsyncBaseMiddleware, BaseHandler, BaseMiddleware, Client, DecodingError, Request, Response, ) MAX_DECODE_LAYERS = 5 class ContentEncodingCheckMiddleware(BaseMiddleware, AsyncBaseMiddleware): def __init__( self, next_handler: BaseHandler | AsyncBaseHandler, *, max_layers: int = MAX_DECODE_LAYERS, ) -> None: self.next = cast(BaseHandler, next_handler) self.async_next = cast(AsyncBaseHandler, next_handler) self._max_layers = max_layers def _check(self, response: Response) -> None: encoding_header = response.headers.get("Content-Encoding") if not encoding_header: return layers = [enc.strip().lower() for enc in encoding_header.split(",") if enc.strip()] if len(layers) > self._max_layers: raise DecodingError(f"Too many Content-Encoding layers ({len(layers)}), maximum is {self._max_layers}") def handle(self, request: Request) -> Response: response = self.next.handle(request) self._check(response) return response async def ahandle(self, request: Request) -> Response: response = await self.async_next.ahandle(request) self._check(response) return response with Client().wrap_with_middleware(lambda next: ContentEncodingCheckMiddleware(next)) as client: ... ```

Related

Alias · CVE (1)

  • CVE-2026-61541 Zapros, a Python HTTP client, prior to version 0.14.0 is vulnerable to denial of service when an application requests content from an… vulnerability

Weakness · CWE (1)

  • CWE-770 Allocation of Resources Without Limits or Throttling weakness

References