Repository navigation
A client receiving an Object with more than 10 binary fields closes the connection #5504
Copy link
Copy link
Open
ErnestHysa/socket.io
#2Labels
questionFurther information is requestedFurther information is requested
Description
Describe the bug
When the Python or Node.js server sends an Object containing more than 10 binary fields to a web browser JS client got via NPM, it fails and the connection is interrupted.
The issue doesn't happen when the package is got via the CDN.
To Reproduce
Socket.IO server version: 4.8.3
Server
import { createServer } from 'http';
import { Server } from 'socket.io';
const PAYLOAD = Buffer.alloc(1); // Size doesn't matter
const httpServer = createServer();
const io = new Server(httpServer, {
cors: { origin: "*" },
});
io.on('connection', (socket) => {
console.log(`[socket ${socket.id}] connected`);
socket.on('request_data', () => {
socket.emit('data', {
"1": PAYLOAD,
"2": PAYLOAD,
"3": PAYLOAD,
"4": PAYLOAD,
"5": PAYLOAD,
"6": PAYLOAD,
"7": PAYLOAD,
"8": PAYLOAD,
"9": PAYLOAD,
"10": PAYLOAD,
"11": PAYLOAD, // Commenting this line makes the issue disappear
});
});
socket.on('disconnect', reason => {
console.log(`[socket ${socket.id}] disconnected: ${reason}`);
});
});
httpServer.listen(8000, 'localhost', () => {
console.log('Server running at http://localhost:8000');
});In Python with python-socketio 5.16.2 and uvicorn[standard] 0.48.0:
import socketio
import uvicorn
sio = socketio.AsyncServer(
async_mode='asgi',
cors_allowed_origins="*",
)
PAYLOAD = b"\x00" * 1 # Size doesn't matter
@sio.event
async def request_data(sid: str) -> None:
await sio.emit('data', {
"1": PAYLOAD,
"2": PAYLOAD,
"3": PAYLOAD,
"4": PAYLOAD,
"5": PAYLOAD,
"6": PAYLOAD,
"7": PAYLOAD,
"8": PAYLOAD,
"9": PAYLOAD,
"10": PAYLOAD,
"11": PAYLOAD, # Commenting this line makes the issue disappear
})
app = socketio.ASGIApp(sio)
if __name__ == '__main__':
uvicorn.run(
app,
host='localhost',
port=8000,
)Socket.IO client version: 4.8.3
Client
import { io } from 'socket.io-client';
const socket = io(`http://localhost:8000`);
socket.on('data', data => {
console.log("Received data");
console.log(data);
});
document.querySelector('#app').innerHTML = `
<button id="requestData" type="button">Request Data</button>
`;
document.querySelector('#requestData').addEventListener(
'click', () => socket.emit('request_data')
);<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>vite-project</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>Expected behavior
The message should be transmitted, showing in the browser console (F12), and the transport not disconnected.
Platform:
- Device: x64 computer
- OS: Linux Mint 22.3
Additional context
The issue does not happen via CDN:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Socket.IO</title>
</head>
<body>
<button id="requestData" type="button">Request Data</button>
<script src="https://cdn.socket.io/4.8.3/socket.io.min.js"></script>
<script>
const socket = io('http://localhost:8000');
document.getElementById('requestData').addEventListener('click', () => {
socket.emit('request_data');
});
socket.on('data', data => {
console.log("Received data");
console.log(data);
});
</script>
</body>
</html>Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
questionFurther information is requestedFurther information is requested
Activity
darrachequesne commentedon May 28, 2026
Hi! This behavior was indeed introduced in b25738c (released in
socket.io-parser@4.2.6, included insocket.io@^4.6.0), in order to prevent a malicious user from making the server run out of memory (by buffering a lot binary attachments forever).See also: CVE-2026-33151
The limit is indeed set to 10 binary attachments. It can be increased with a custom
parser:There is no release of the
socket.io-clientpackage with the fix yet, that's why the bundle from the CDN does not show this behavior.guillaume-mueller commentedon May 28, 2026
I'm not sure to understand.
Actually I need to use a Python server and a browser JS client got from NPM and bundled with Vite.
I can do a variety of server and client combinations among Python, Node.js and browser JS and I think the issue is only caused by using the
socket.io-clientNPM package, but the solution you give involves tweaking the server.Here is also a Python client using python-socketio[asyncio-client] 5.16.2, which also doesn't suffer the issue while communicating with either the Python or Node.js server as described in my first message:
guillaume-mueller commentedon May 28, 2026
OK, I saw the
parseroption is also settable to the client, so this solves the issue:Now I don't understand the security concern addressed.
When I use the Node.js server described in my first message with a Python or browser JS via CDN client, the issue doesn't occur.
So finally the limitation is only in the client, which a malicious end user can tweak as they wish.
Also it would have been convenient if this behavior was documented, because I struggled quite a lot.
nml0bts commentedon May 29, 2026
I believe CDN bundle is built against an older version of the parser (
socket.io-parser< 4.2.6), thus the difference.