CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-69229

Algorithmic Complexity DoS in aiohttp via Chunked Transfer Encoding

Alon Barad
Alon Barad
Software Engineer

Feb 28, 2026·6 min read·104 visits

Executive Summary (TL;DR)

aiohttp <= 3.13.2 contains a Denial of Service vulnerability triggered by HTTP chunked encoding. The internal handling of chunk delimiters used a data structure with $O(N)$ removal costs, leading to $O(N^2)$ overall complexity when processing many chunks. Attackers can freeze the application event loop by sending crafted requests. Fixed in 3.13.3.

A resource exhaustion vulnerability exists in aiohttp versions 3.13.2 and earlier, specifically affecting the handling of HTTP chunked transfer encoding. The vulnerability arises from an algorithmic complexity flaw ($O(N^2)$) in the `StreamReader` class where chunk boundaries were managed using a standard Python list. A remote, unauthenticated attacker can exploit this by sending a request with a massive number of small chunks, forcing the server to perform excessive memory shifting operations during list manipulation. In an asynchronous framework like aiohttp, this CPU-bound operation blocks the main event loop, preventing the server from handling other concurrent connections and resulting in a Denial of Service (DoS).

Vulnerability Overview

aiohttp is a foundational asynchronous HTTP client/server framework for Python, heavily relied upon for its ability to handle high-concurrency workloads via the asyncio event loop. CVE-2025-69229 identifies a critical performance flaw in the framework's core stream processing logic.

The vulnerability is a classic case of algorithmic complexity exhaustion. It specifically targets the mechanism aiohttp uses to parse and track incoming HTTP streams utilizing Transfer-Encoding: chunked. When a server receives a chunked request, it must track the boundaries of each chunk to reconstruct the full payload.

In affected versions, the implementation failed to account for the computational cost of managing metadata for high-frequency, small-payload chunks. While the framework correctly limited the total bytes buffered (flow control based on payload size), it did not limit the number of chunks buffered. Furthermore, the data structure used to track these chunks incurred a linear cost for removal operations. This combination allows an attacker to manipulate the server into executing a quadratic number of operations relative to the number of chunks sent, effectively effectively converting a small network payload into a massive CPU workload that halts the single-threaded event loop.

Root Cause Analysis

The root cause of this vulnerability lies in aiohttp/streams.py within the StreamReader class. This class is responsible for managing the buffer of incoming data. The specific flaw manifests in two interacting components: an inefficient data structure choice and missing flow control for metadata.

1. Inefficient List Operations ($O(N^2)$)

The StreamReader class maintained a list called _http_chunk_splits to track the indices of chunk boundaries. When consuming the stream (e.g., during readchunk() calls), the code retrieved the next chunk position using the standard Python list method pop(0):

# Vulnerable implementation
pos = self._http_chunk_splits.pop(0)

In CPython, list is implemented as a dynamic array. Removing the first element (index 0) requires shifting all subsequent elements in memory to fill the gap. This operation has a time complexity of $O(N)$, where $N$ is the number of elements in the list.

If an attacker sends a request comprising $N$ chunks, the server performs $N$ pop operations. The total complexity becomes the sum of the series, resulting in $O(N^2)$. For a request with 50,000 chunks, the server performs billions of memory move operations. Since Python's asyncio loop is single-threaded, this CPU-intensive task blocks the loop entirely, causing all other tasks (heartbeats, other requests, timers) to stall.

2. Lack of Metadata Backpressure

Prior to the fix, aiohttp implemented flow control (backpressure) based solely on the byte size of the buffered data (high_water mark). It did not count the number of chunks. An attacker could send thousands of 1-byte chunks. While the total byte count would remain low (staying under the byte-limit radar), the _http_chunk_splits list would grow aggressively. The application would continue reading from the transport, populating this list unbounded, before the expensive pop(0) loop began.

Code Analysis & Patch

The remediation for CVE-2025-69229 involves two key commits that address both the algorithmic inefficiency and the flow control logic.

Fix 1: Changing Data Structures

The primary fix (Commit dc3170b...) replaces the standard list with collections.deque. A deque (double-ended queue) is implemented as a doubly linked list of blocks, allowing for $O(1)$ complexity when popping from either end.

# aiohttp/streams.py
 
- from typing import Any, Awaitable, Callable, List, Optional, Pattern, Tuple
+ from typing import Any, Awaitable, Callable, Deque, List, Optional, Pattern, Tuple
 
  class StreamReader:
      def __init__(self, ...):
-         self._http_chunk_splits: Optional[List[int]] = None
+         self._http_chunk_splits: Optional[Deque[int]] = None
 
      def _read_nowait_chunk(self, n: int) -> bytes:
          ...
-         pos = self._http_chunk_splits.pop(0)
+         pos = self._http_chunk_splits.popleft()

This change ensures that processing $N$ chunks results in $O(N)$ total work rather than $O(N^2)$, neutralizing the CPU exhaustion vector.

Fix 2: Metadata Flow Control

The secondary fix (Commit 4ed97a4...) introduces logic to pause the transport if the count of buffered chunks becomes too high, regardless of their total byte size. This prevents the queue from growing indefinitely.

# Logic added to limit the number of pending chunks
self._high_water_chunks = max(3, limit // 4)
self._low_water_chunks = max(2, self._high_water_chunks // 2)
 
# In feed_data or similar ingestion methods:
if len(self._http_chunk_splits) > self._high_water_chunks:
    self._transport.pause_reading()

These combined changes ensure that the application handles chunked data efficiently and refuses to buffer excessive metadata.

Exploitation Mechanics

While no public Proof-of-Concept (PoC) is currently circulating in the wild, the exploitation methodology is straightforward for a researcher understanding the root cause. The attack relies on the HTTP Transfer-Encoding: chunked header.

Attack Prerequisites

  1. Target: An aiohttp server (v3.13.2 or older) exposing an endpoint that reads the request body.
  2. Network Access: Ability to send HTTP requests to the target.
  3. Authentication: None required (unless the endpoint itself is protected, but the parsing happens early in the stack).

Attack Steps

  1. Initiate Connection: The attacker opens a TCP connection to the server.
  2. Send Headers: The attacker sends a POST or PUT request with Transfer-Encoding: chunked.
  3. Stream Payload: Instead of sending reasonable chunks (e.g., 4KB), the attacker sends a massive stream of tiny chunks. For example, 100,000 chunks each containing 1 byte of data.
POST /api/upload HTTP/1.1
Host: target.com
Transfer-Encoding: chunked
 
1
A
1
B
1
C
... (repeated 100,000 times)
0
 

Result

As the server receives these chunks, it appends their split positions to _http_chunk_splits. When the application logic attempts to read this body (e.g., await request.text()), the StreamReader enters the loop calling pop(0) for every chunk. The Python process hits 100% CPU usage on a single core. Because asyncio is cooperative multitasking, the event loop is blocked. The server stops responding to health checks, drops existing connections, and cannot accept new ones until the loop finishes processing the massive list.

Impact & Remediation

The impact of CVE-2025-69229 is classified as Medium (CVSS 5.3) by NVD, primarily because it affects availability without compromising confidentiality or integrity. However, in production environments relying on aiohttp for microservices or public-facing APIs, the operational impact can be severe.

Operational Impact

  • Service Outage: A single attacker can degrade or completely halt service availability.
  • Resource Waste: Autoscaling groups might spawn unnecessary instances in response to the perceived load/unresponsiveness, increasing cloud costs.
  • Cascading Failures: If the vulnerable service is a gateway or middleware, downstream dependencies may time out, causing system-wide instability.

Remediation Strategy

Security teams and developers should prioritize the following actions:

  1. Upgrade Immediately: Update aiohttp to version 3.13.3 or later. This version includes both the deque optimization and the chunk-count limits.
    pip install aiohttp>=3.13.3
  2. Dependency Audit: Check transitive dependencies. Many Python libraries depend on aiohttp. Run pipdeptree or similar tools to ensure underlying libraries are using the patched version.
  3. WAF Configuration: As a temporary mitigation, configure Web Application Firewalls (WAF) to inspect Transfer-Encoding headers. Block requests with an excessive number of chunks or set a lower limit on the maximum request body size if chunk counting is not possible.

Official Patches

aio-libsGitHub Security Advisory GHSA-g84x-mcqj-x9qq

Fix Analysis (2)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
EPSS Probability
0.05%
Top 100% most exploited

Affected Systems

aiohttp

Affected Versions Detail

Product
Affected Versions
Fixed Version
aiohttp
aio-libs
<= 3.13.23.13.3
AttributeDetail
CWE IDCWE-770
Attack VectorNetwork (Remote)
CVSS v3.15.3 (Medium)
ImpactDenial of Service (DoS)
Exploit StatusNo Known PoC
EPSS Score0.05% (Low Probability)

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.003Application or System Exploitation
Impact
CWE-770
Allocation of Resources Without Limits or Throttling

Allocation of Resources Without Limits or Throttling

Vulnerability Timeline

Patches committed to master branch
2026-01-03
GHSA-g84x-mcqj-x9qq published
2026-01-05
CVE-2025-69229 published in NVD
2026-01-06

References & Sources

  • [1]NVD - CVE-2025-69229
  • [2]aiohttp Changelog

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•16 minutes ago•CVE-2026-116580
7.3

CVE-2026-116580: Unvalidated Method Invocation via Identifier Reuse in Seroval Deserializer

Seroval versions prior to 1.6.8 contain an insecure deserialization vulnerability (CWE-502) in the `fromJSON` parser. When reconstructing `AsyncIteratorFactoryInstance` or `IteratorFactoryInstance` nodes, the deserializer verifies the source node type using its identifier in the AST lookup table rather than verifying the runtime identity of the deserialized object. Because unmarked node identifiers omitted from the `m` reference array can be reused in vanilla deserialization mode, an attacker can substitute an arbitrary plain object or plugin-produced value as the stream source. This causes the runtime to invoke `.on(listener)` on an attacker-controlled target.

Amit Schendel
Amit Schendel
0 views•12 min read
•about 1 hour ago•CVE-2026-116584
7.5

CVE-2026-116584: Denial of Service via Unvalidated Node Element Lists in Seroval

A Denial of Service (DoS) vulnerability exists in the Seroval JavaScript serialization library affecting versions 1.4.1 through 1.6.7. The deserialization routines fromJSON and fromCrossJSON fail to verify that node element lists are actual JavaScript Array primitives before reading their length property. An unauthenticated remote attacker can supply a compact, malformed JSON payload containing an array-like object with an arbitrary length value, causing unbounded memory allocation and synchronous loop iterations that block the event loop or crash the process via heap exhaustion.

Amit Schendel
Amit Schendel
2 views•10 min read
•about 2 hours ago•CVE-2026-116581
7.5

CVE-2026-116581: Unauthenticated Event-Loop Denial of Service via Unvalidated Sequence Indices in Seroval

Seroval, a JavaScript serialization library used for transferring complex structures across network boundaries, contains an input validation vulnerability in versions prior to 1.6.8. The `fromJSON` and `fromCrossJSON` deserializers fail to validate array element lists and the termination boundaries (`done` and `throw` indices) of sequence nodes. By supplying out-of-bounds indices or forged array-like structures, an unauthenticated remote attacker can construct an iterator with an unreachable exit condition or trigger excessive loop iterations, halting the single-threaded JavaScript event loop and causing a denial of service.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 3 hours ago•CVE-2026-116582
4.7

CVE-2026-116582: Cross-Site Scripting via Unescaped RegExp Serialization in Seroval

CVE-2026-116582 is an improper output escaping vulnerability in the Seroval JavaScript serialization library that leads to cross-site scripting (XSS). When Seroval serializes RegExp objects into executable JavaScript literals for embedding in HTML script elements, it fails to neutralize the less-than character ('<'). If an application constructs a regular expression from untrusted input and embeds the serialized output inside an inline script block during server-side rendering (SSR), an attacker can inject a closing script tag to break out of the JavaScript context and execute arbitrary client-side code.

Amit Schendel
Amit Schendel
3 views•11 min read
•about 4 hours ago•CVE-2026-116583
5.3

CVE-2026-116583: Code Injection via TypedArray Constructor Property Spoofing in Seroval

CVE-2026-116583 (GHSA-f86p-h4j2-7qgj) is a code injection and cross-site scripting (XSS) vulnerability in Seroval, a JavaScript object serialization library. In versions 1.6.0 prior to 1.6.11, Seroval derives the constructor name of a TypedArray directly from the `current.constructor.name` property expression during serialization. If an attacker supplies untrusted properties that are merged onto a TypedArray instance, an own `constructor` property overrides the prototype property and gets emitted unescaped after the `new` keyword in the generated JavaScript output. Evaluating or rendering this output in a browser or JavaScript runtime results in arbitrary code execution.

Alon Barad
Alon Barad
4 views•8 min read
•about 5 hours ago•GHSA-JF75-Q64Q-G65R
6.5

GHSA-jf75-q64q-g65r: NoSQL Query Manipulation and Partial Authentication Bypass in Waline Server

An improper input validation and NoSQL query construction vulnerability exists in the Waline comment system server (@waline/vercel) version 1.40.3 and earlier. When MongoDB is used as the backend storage engine, the POST /api/token authentication endpoint fails to validate that the user-supplied email parameter is a string. Supplying a JSON object or array operator causes the MongoDB storage adapter to omit the email filter or construct an unintended match-all query, returning all user records and allowing unauthenticated attackers to target the site administrator account directly without knowing the administrator's email address.

Alon Barad
Alon Barad
3 views•10 min read