Skip to content

Commit a70800d

Browse files
fix: properly handle invalid data sent by a malicious websocket client
**IMPORTANT SECURITY FIX** A malicious client could send a specially crafted HTTP request, triggering an uncaught exception and killing the Node.js process: > RangeError: Invalid WebSocket frame: RSV2 and RSV3 must be clear > at Receiver.getInfo (/.../node_modules/ws/lib/receiver.js:176:14) > at Receiver.startLoop (/.../node_modules/ws/lib/receiver.js:136:22) > at Receiver._write (/.../node_modules/ws/lib/receiver.js:83:10) > at writeOrBuffer (internal/streams/writable.js:358:12) This bug was introduced by [1], included in `engine.io@4.0.0`, so previous releases are not impacted. [1]: f3c291f Thanks to Marcus Wejderot from Mevisio for the responsible disclosure. Backported from master: c0e194d
1 parent 9534355 commit a70800d

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

lib/server.js

-3
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,6 @@ class Server extends EventEmitter {
372372
client.maybeUpgrade(transport);
373373
}
374374
} else {
375-
// transport error handling takes over
376-
socket.removeListener("error", onUpgradeError);
377-
378375
this.handshake(req._query.transport, req);
379376
}
380377

test/server.js

+40
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,46 @@ describe("server", () => {
107107
}
108108
);
109109
});
110+
111+
it("should not throw when the client sends invalid data during the handshake (ws only)", done => {
112+
listen(port => {
113+
// will throw "RangeError: Invalid WebSocket frame: RSV2 and RSV3 must be clear"
114+
request
115+
.get(`http://localhost:${port}/engine.io/`)
116+
.set("connection", "upgrade")
117+
.set("upgrade", "websocket")
118+
.set("Sec-WebSocket-Version", "13")
119+
.set("Sec-WebSocket-Key", "DXR4dX615eRds8nRmlhqtw==")
120+
.query({ transport: "websocket", EIO: 4 })
121+
.send("test")
122+
.end(() => {});
123+
124+
setTimeout(done, 50);
125+
});
126+
});
127+
128+
it("should not throw when the client sends invalid data during the handshake (upgrade)", done => {
129+
listen(port => {
130+
request
131+
.get(`http://localhost:${port}/engine.io/`)
132+
.query({ transport: "polling", EIO: 4 })
133+
.end((err, res) => {
134+
const sid = JSON.parse(res.text.substring(1)).sid;
135+
136+
request
137+
.get(`http://localhost:${port}/engine.io/`)
138+
.set("connection", "upgrade")
139+
.set("upgrade", "websocket")
140+
.set("Sec-WebSocket-Version", "13")
141+
.set("Sec-WebSocket-Key", "DXR4dX615eRds8nRmlhqtw==")
142+
.query({ transport: "websocket", EIO: 4, sid })
143+
.send("test")
144+
.end(() => {});
145+
146+
setTimeout(done, 50);
147+
});
148+
});
149+
});
110150
});
111151

112152
describe("handshake", () => {

0 commit comments

Comments
 (0)