Skip to content

Commit c0e194d

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 `[email protected]`, so previous releases are not impacted. [1]: f3c291f Thanks to Marcus Wejderot from Mevisio for the responsible disclosure.
1 parent b04967b commit c0e194d

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

lib/server.ts

-3
Original file line numberDiff line numberDiff line change
@@ -609,9 +609,6 @@ export class Server extends BaseServer {
609609
client.maybeUpgrade(transport);
610610
}
611611
} else {
612-
// transport error handling takes over
613-
websocket.removeListener("error", onUpgradeError);
614-
615612
const closeConnection = (errorCode, errorContext) =>
616613
abortUpgrade(socket, errorCode, errorContext);
617614
this.handshake(req._query.transport, req, closeConnection);

test/server.js

+40
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,46 @@ describe("server", () => {
157157
}
158158
);
159159
});
160+
161+
it("should not throw when the client sends invalid data during the handshake (ws only)", done => {
162+
listen(port => {
163+
// will throw "RangeError: Invalid WebSocket frame: RSV2 and RSV3 must be clear"
164+
request
165+
.get(`http://localhost:${port}/engine.io/`)
166+
.set("connection", "upgrade")
167+
.set("upgrade", "websocket")
168+
.set("Sec-WebSocket-Version", "13")
169+
.set("Sec-WebSocket-Key", "DXR4dX615eRds8nRmlhqtw==")
170+
.query({ transport: "websocket", EIO: 4 })
171+
.send("test")
172+
.end(() => {});
173+
174+
setTimeout(done, 50);
175+
});
176+
});
177+
178+
it("should not throw when the client sends invalid data during the handshake (upgrade)", done => {
179+
listen(port => {
180+
request
181+
.get(`http://localhost:${port}/engine.io/`)
182+
.query({ transport: "polling", EIO: 4 })
183+
.end((err, res) => {
184+
const sid = JSON.parse(res.text.substring(1)).sid;
185+
186+
request
187+
.get(`http://localhost:${port}/engine.io/`)
188+
.set("connection", "upgrade")
189+
.set("upgrade", "websocket")
190+
.set("Sec-WebSocket-Version", "13")
191+
.set("Sec-WebSocket-Key", "DXR4dX615eRds8nRmlhqtw==")
192+
.query({ transport: "websocket", EIO: 4, sid })
193+
.send("test")
194+
.end(() => {});
195+
196+
setTimeout(done, 50);
197+
});
198+
});
199+
});
160200
});
161201

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

0 commit comments

Comments
 (0)