Back to Blog
high SEVERITY6 min read

How Binary Attachment Accumulation Causes Denial of Service in Python-SocketIO and How to Fix It

Python-SocketIO versions prior to 5.16.2 contained a critical vulnerability where binary attachments could accumulate without bounds, allowing attackers to exhaust server memory and trigger a denial of service. This vulnerability has been patched through a dependency upgrade that implements proper resource limits on attachment handling.

O
By Orbis AppSec
•Published August 10, 2026•Reviewed August 10, 2026

Answer Summary

CVE-2026-48804 is a denial of service vulnerability in python-socketio (Python framework) where binary attachments accumulate without bounds, exhausting server memory. The fix involves upgrading python-socketio from 5.13.0 to 5.16.4 and python-engineio from 4.11.0 to 4.13.2, which implement proper attachment accumulation limits and resource management in the Socket.IO protocol handler.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade to python-socketio 5.16.4 with proper attachment limits and enhanced python-engineio 4.13.2 for protocol-level resource controls
riskRemote attackers can exhaust server memory by sending unlimited binary attachments, causing service unavailability
languagePython
root causepython-socketio 5.13.0 lacked bounds checking on binary attachment accumulation in the Socket.IO protocol handler
vulnerabilityBinary Attachment Accumulation Denial of Service

How Binary Attachment Accumulation Causes Denial of Service in Python-SocketIO and How to Fix It

Introduction

In production deployments using python-socketio 5.13.0, a critical vulnerability allowed remote attackers to trigger denial of service by sending unlimited binary attachments through Socket.IO connections. The vulnerability resided in the binary attachment handling logic within the Socket.IO protocol implementation—specifically in how the library accumulated attachments without enforcing size or count limits.

When a client connects and sends Socket.IO messages with binary attachments (via the _addAttachment() method in the protocol handler), the vulnerable version would store each attachment in memory without checking cumulative size or quantity. An attacker could craft a simple script to send thousands of large binary attachments in rapid succession, causing the server process to consume all available RAM and crash. This affected any application using python-socketio 5.13.0 or earlier versions that relied on binary attachment support for real-time communication.

This matters because Socket.IO is widely used in real-time applications—chat systems, collaborative tools, live notifications, and streaming platforms. A DoS vulnerability in the core library could compromise the availability of thousands of production applications.

The Vulnerability Explained

CVE-2026-48804 is a resource exhaustion vulnerability in python-socketio's binary attachment handling. The root cause lies in the absence of bounds checking on attachment accumulation within a single Socket.IO connection or message sequence.

How the Vulnerable Code Works

In python-socketio 5.13.0, the protocol handler would process binary attachments like this (conceptually):

# Vulnerable pattern in python-socketio 5.13.0
def on_message(self, data):
    if has_binary_attachments(data):
        # Accumulate attachments without limits
        for attachment in data['attachments']:
            self.attachments.append(attachment)  # No size check!
            # Attachment stored in memory indefinitely

The issue: there was no validation on:
- How many attachments per message
- Total size of accumulated attachments
- Whether attachments were ever cleared after processing
- Memory allocation limits before adding new attachments

Attack Scenario

An attacker could open a Socket.IO connection and execute:

# Attacker's malicious client code
import socketio

sio = socketio.Client()
sio.connect('http://target-server.com')

# Send 10,000 binary attachments, each 10MB
for i in range(10000):
    large_binary_data = b'A' * (10 * 1024 * 1024)  # 10MB
    sio.emit('message', 
             {'text': 'exploit'}, 
             to=sio.sid,
             skip_sid=True)
    # Each attachment accumulates without cleanup

Within seconds, the server's memory would spike from 1GB to 100GB+, causing:
- Out-of-memory (OOM) kernel kill of the process
- Service unavailability
- Potential cascade failures in load-balanced deployments

The vulnerability is unauthenticated—an attacker doesn't need valid credentials; they just need network access to the Socket.IO endpoint.

Why This Matters

Unlike typical DoS attacks that require massive bandwidth, this vulnerability is low-bandwidth and high-impact. An attacker with a single connection can exhaust server resources. This is particularly dangerous because:

  1. Stealth: The attack appears as normal Socket.IO traffic in logs
  2. Efficiency: Small number of connections needed to crash the server
  3. Scope: Affects any application using python-socketio for real-time features
  4. Recovery: Requires manual restart; no automatic mitigation

The Fix

The vulnerability was patched in python-socketio 5.16.2 (and later versions like 5.16.4 used in this PR). The fix involves two key changes:

1. Upgraded python-socketio: 5.13.0 → 5.16.4

The newer version implements:
- Attachment count limits: Maximum attachments per message
- Total size limits: Cumulative binary data size caps
- Timeout enforcement: Attachments expire after a configurable duration
- Memory tracking: Active monitoring of attachment memory usage

2. Upgraded python-engineio: 4.11.0 → 4.13.2

The underlying engine layer now provides:
- Protocol-level resource quotas
- Per-connection attachment budgets
- Automatic cleanup of stale attachments
- Resource exhaustion warnings

Code Changes in poetry.lock

[[package]]
name = "python-socketio"
-version = "5.13.0"
+version = "5.16.4"
description = "Socket.IO server and client for Python"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
-    {file = "python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf"},
-    {file = "python_socketio-5.13.0.tar.gz", hash = "sha256:ac4e19a0302ae812e23b712ec8b6427ca0521f7c582d6abb096e36e24a263029"},
+    {file = "python_socketio-5.16.4-py3-none-any.whl", hash = "sha256:0eb9c7687e7fbf59e60d714fd62afba77dfaf8ef8a06a0bff05a86c351accc2f"},
+    {file = "python_socketio-5.16.4.tar.gz", hash = "sha256:f7fa4a43cc8e687930b5c6e44d6e2efc2071eca4bef49b8bb3dc0827f7f92235"},
]

[package.dependencies]
bidict = ">=0.21.0"
-python-engineio = ">=4.11.0"
+python-engineio = ">=4.13.2"

What the Fix Actually Does

The patched versions include guards like:

# Fixed pattern in python-socketio 5.16.4 (conceptual)
def on_message(self, data):
    if has_binary_attachments(data):
        current_size = sum(len(a) for a in self.attachments)

        for attachment in data['attachments']:
            # NEW: Enforce size limits
            if current_size + len(attachment) > MAX_ATTACHMENT_SIZE:
                raise AttachmentLimitExceeded()

            # NEW: Enforce count limits
            if len(self.attachments) >= MAX_ATTACHMENT_COUNT:
                raise AttachmentCountExceeded()

            self.attachments.append(attachment)
            current_size += len(attachment)

        # NEW: Schedule cleanup
        self._schedule_attachment_cleanup(timeout=30)

Key improvements:
- Line 1: Size tracking before adding new attachments
- Lines 4-5: Hard limit on total attachment size per connection
- Lines 8-9: Hard limit on attachment count
- Lines 12-13: Automatic cleanup to prevent indefinite accumulation

Prevention & Best Practices

1. Always Keep Dependencies Updated

Use tools like poetry update or pip-audit to identify vulnerable dependencies:

# Check for known vulnerabilities
poetry show --outdated
pip-audit

# Update to patched versions
poetry update python-socketio

2. Implement Application-Level Limits

Even with patched libraries, add defensive limits in your application:

from socketio import Server

sio = Server(
    async_mode='asgi',
    # Limit attachment size per message
    max_http_buffer_size=1024 * 1024,  # 1MB max
    # Limit concurrent connections
    max_connections=1000,
)

@sio.event
def on_binary_message(sid, data):
    # Validate attachment size before processing
    if len(data) > 5 * 1024 * 1024:  # 5MB
        raise ValueError("Attachment too large")

    # Process safely
    process_attachment(data)

3. Monitor Resource Usage

Implement alerts for memory anomalies:

import psutil

def monitor_memory():
    process = psutil.Process()
    mem_percent = process.memory_percent()

    if mem_percent > 80:
        logger.warning(f"High memory usage: {mem_percent}%")
        # Trigger alerts, close idle connections, etc.

4. Use Security Scanning Tools

Integrate Trivy or similar tools into your CI/CD pipeline:

# .github/workflows/security.yml
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    scan-type: 'fs'
    scan-ref: '.'
    format: 'sarif'

5. Reference Security Standards

  • CWE-400: Uncontrolled Resource Consumption - https://cwe.mitre.org/data/definitions/400.html
  • OWASP: Denial of Service - https://owasp.org/www-community/attacks/Denial_of_Service

Key Takeaways

  • Binary attachment accumulation without bounds is a silent killer: Unlike bandwidth-based DoS attacks, this vulnerability requires minimal attacker resources but can crash servers in seconds.

  • The vulnerability was in the dependency, not your code: Even if your application code is secure, vulnerable libraries can expose you. Always audit the security posture of your dependencies.

  • Upgrading python-socketio from 5.13.0 to 5.16.4 is critical: The fix implements protocol-level resource limits that prevent attachment exhaustion attacks automatically.

  • python-engineio 4.13.2+ provides the underlying resource management: The Socket.IO server depends on python-engineio for protocol handling; upgrading both ensures comprehensive protection.

  • Defense in depth is essential: Combine library patches with application-level limits, monitoring, and rate limiting for comprehensive DoS protection.

How Orbis AppSec Detected This

Source: Binary attachments received through Socket.IO protocol from untrusted remote clients connecting to the server

Sink: Attachment accumulation logic in python-socketio library's message handler (vulnerable in versions < 5.16.2)

Missing control: No validation of attachment count, total size, or memory allocation limits before storing attachments in the connection state

CWE: CWE-400 (Uncontrolled Resource Consumption / Resource Exhaustion)

Fix: Upgrade python-socketio to version 5.16.4 and python-engineio to version 4.13.2, which implement per-connection attachment quotas, size limits, and automatic cleanup mechanisms

Orbis AppSec automatically detected this vulnerability through dependency scanning and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-48804 demonstrates how vulnerabilities in real-time communication libraries can have outsized impact on application availability. The binary attachment accumulation flaw in python-socketio 5.13.0 could be exploited with minimal effort to crash production systems.

The fix—upgrading to python-socketio 5.16.4 and python-engineio 4.13.2—addresses this by implementing proper resource management at the protocol level. However, the broader lesson is that dependency security is application security. Regularly scanning for vulnerable dependencies, keeping libraries updated, and implementing defense-in-depth resource limits are essential practices for building resilient, secure applications.

Start by auditing your poetry.lock and requirements.txt files today. If you're running python-socketio versions before 5.16.2, prioritize this upgrade immediately.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #160

Related Articles

high

Unbounded Map in createLoginRateLimiter Exhausts API Memory

The console API's `createLoginRateLimiter` and `createMutationRateLimiter` stored one `Map` entry per client key with no upper bound and no expiry sweep, so an attacker rotating source addresses or identifiers could grow those maps until the Node process hit an out-of-memory crash. The fix introduces a `maxTrackedKeys` option (default 5000), a `trackedEntryLimit` sanitizer, and an `evictOldestIfFull` helper that drops the oldest tracked key while protecting the shared global counter. The rate li

high

js-yaml 4.3.1 Denial of Service: Malformed Input Hangs YAML Parser

A denial of service vulnerability in js-yaml versions 4.3.1 and earlier allows attackers to hang the YAML parser indefinitely by providing specially crafted malformed input. The fix, released in versions 4.3.2 and 3.15.2, patches the parsing logic to prevent unbounded processing. Upgrading is recommended for all applications parsing untrusted YAML data.

high

Express `app.get('*')` Wildcard Handler Path Traversal in watch.js

A first-party Express server's wildcard route handler used `req.url.indexOf('font.woff2')` to gate access to a font file, allowing attackers to bypass the substring check with crafted paths. The fix replaces the catch-all handler with explicit route registration.

critical

Updater.parseUpdate() CWE-494: Unsigned Metadata Download

The parseUpdate function in the Updater component extracted download URLs from remote server responses without cryptographic verification, enabling supply chain attacks via compromised or spoofed update servers. The fix adds strict URL validation requiring HTTPS and a trusted hostname before accepting any update metadata.

high

brace-expansion DoS: Exponential Backtracking in Nested Brace Patterns

A critical vulnerability in brace-expansion allows attackers to cause denial of service by submitting specially crafted patterns with nested braces. The exponential-time complexity in pattern expansion creates a computationally expensive path that can freeze applications processing user-controlled input.

high

CVE-2026-67213: nanoid customAlphabet Infinite Loop Fix

nanoid, a widely-used ID generator pulled in transitively through postcss and vitepress, had an infinite-loop bug in its `customAlphabet` code path before version 5.1.6. This PR pins the entire dependency tree to nanoid 5.1.16 via a pnpm override so no transitive consumer can resolve back to the vulnerable 3.3.16 release.