Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-54278

CVE-2026-54278: AIOHTTP DoS Vulnerability via Compression

CVE-2026-54278 is a denial of service vulnerability in AIOHTTP that allows attackers to exploit compressed payloads as zip bombs. This post covers the technical details, affected versions, and mitigation strategies.

Published:

CVE-2026-54278 Overview

CVE-2026-54278 affects AIOHTTP, an asynchronous HTTP client/server framework for asyncio and Python. The vulnerability exists in versions prior to 3.14.1, where compressed request bodies can be decompressed into memory as a single chunk during cleanup. An attacker can send a crafted compressed payload that expands into a large memory allocation, producing a zip bomb edge case that leads to denial of service (DoS). The flaw is classified under CWE-409: Improper Handling of Highly Compressed Data (Data Amplification). AIOHTTP maintainers addressed the issue in release 3.14.1 by bounding the unread compressed drain operation.

Critical Impact

Remote unauthenticated attackers can trigger memory exhaustion in AIOHTTP server processes by sending small compressed payloads that expand into large in-memory buffers during request cleanup.

Affected Products

  • AIOHTTP versions prior to 3.14.1
  • Python asyncio HTTP server applications built on AIOHTTP
  • Services accepting compressed request bodies via AIOHTTP

Discovery Timeline

  • 2026-06-22 - CVE-2026-54278 published to NVD
  • 2026-06-23 - Last updated in NVD database

Technical Details for CVE-2026-54278

Vulnerability Analysis

The vulnerability resides in the stream reading logic of AIOHTTP, specifically in aiohttp/streams.py. When a compressed request body is processed and the connection enters cleanup, the framework reads the entire buffered payload in a single operation by passing n == -1 to the chunk reader. This unbounded read concatenates every queued chunk and decompresses them into a single in-memory bytes object.

An attacker can submit a small compressed payload, such as a highly compressible deflate or gzip stream, that expands to many gigabytes when decompressed. Because the cleanup path does not enforce a byte limit, the decompressed output is materialized entirely in process memory. Repeated requests amplify the memory pressure on the worker process, leading to denial of service.

Root Cause

The root cause is unbounded buffer draining during connection cleanup. The previous implementation iterated through the buffer without imposing a maximum size when n == -1, allowing a compressed payload to fully decompress before any size check. This matches the CWE-409 pattern of failing to handle highly compressed data safely.

Attack Vector

The attack is network-based and requires no authentication or user interaction. An attacker sends an HTTP request with Content-Encoding: gzip or deflate and a body crafted to expand significantly when decompressed. The AIOHTTP server processes the body during request cleanup and allocates the full decompressed payload in memory.

python
         """Read not more than n bytes, or whole buffer if n == -1"""
         self._timer.assert_timeout()
 
-        chunks = []
+        if n == -1:
+            # Drain only chunks present now; _read_nowait_chunk() can
+            # re-entrantly resume_reading() and refill the buffer.
+            count = len(self._buffer)
+            if count == 1:
+                return self._read_nowait_chunk(-1)
+            return b"".join([self._read_nowait_chunk(-1) for _ in range(count)])
+
+        chunks: list[bytes] = []
         while self._buffer:
             chunk = self._read_nowait_chunk(n)
             chunks.append(chunk)
-            if n != -1:
-                n -= len(chunk)
-                if n == 0:
-                    break
+            n -= len(chunk)
+            if n == 0:
+                break
 
         return b"".join(chunks) if chunks else b""

Source: GitHub Commit 4f7480e. The patch bounds the drain to chunks present at the moment of the read, preventing re-entrant resume_reading() calls from continuously refilling and amplifying the buffer.

Detection Methods for CVE-2026-54278

Indicators of Compromise

  • Spikes in resident memory usage for AIOHTTP worker processes following requests with Content-Encoding: gzip or deflate
  • HTTP requests with small Content-Length values but disproportionately large decompressed sizes
  • Worker process crashes or MemoryError exceptions in AIOHTTP application logs
  • Repeated requests from the same source carrying compressed bodies to endpoints that accept request bodies

Detection Strategies

  • Inventory Python services and identify AIOHTTP versions in use via pip show aiohttp or dependency manifests such as requirements.txt and pyproject.toml
  • Deploy WAF or reverse proxy rules that inspect the decompression ratio of incoming requests and reject payloads exceeding a safe expansion threshold
  • Correlate process-level memory metrics with HTTP access logs filtered on Content-Encoding headers

Monitoring Recommendations

  • Alert on AIOHTTP worker resident set size (RSS) exceeding a baseline percentile, particularly when correlated with compressed request traffic
  • Track HTTP 5xx responses and abrupt worker restarts in application telemetry
  • Enable structured logging for request size, declared encoding, and processing duration to support post-incident analysis

How to Mitigate CVE-2026-54278

Immediate Actions Required

  • Upgrade AIOHTTP to version 3.14.1 or later across all affected services
  • Audit application code that accepts compressed request bodies and ensure explicit body size limits are enforced before decompression
  • Deploy upstream rate limiting and request size caps at load balancers, ingress controllers, or WAFs

Patch Information

The vulnerability is fixed in AIOHTTP 3.14.1. Refer to the GitHub Security Advisory GHSA-g3cq-j2xw-wf74 and the upstream commit for technical details. The patch bounds buffer draining during cleanup so that compressed payloads cannot be decompressed into a single unbounded allocation.

Workarounds

  • Disable acceptance of compressed request bodies at the application or proxy layer where Content-Encoding is not required
  • Enforce strict request body size limits and compression ratio checks at an upstream reverse proxy such as NGINX or Envoy
  • Apply per-client connection and request rate limits to reduce the impact of repeated DoS attempts
bash
# Upgrade aiohttp to the patched release
pip install --upgrade 'aiohttp>=3.14.1'

# Verify installed version
python -c "import aiohttp; print(aiohttp.__version__)"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.