~ / search / GHSA-5vjj-2r48-q622

GHSA-5vjj-2r48-q622

Zapros has an Unbounded Content-Encoding decompression chain that allows denial of service

Source: GitHub Advisory Database (reviewed) Moderate CVE-2026-61541

Packages

EcosystemPackageAffectedFixed in
PyPI zapros < 0.14.0 0.14.0

Details

As written in the advisory (Markdown source, shown as plain text).

### 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: ... ```

References

External links from the advisory. They lead to third-party sites.