ws: Websocket RangeError: Invalid WebSocket frame: RSV2 and RSV3 must be clear

  • [ x] I’ve searched for any related issues and avoided creating a duplicate issue.

Description

I’m using ws as a client in my node application, and when I attempt to connect to the host, the connection is closed with the error ‘Websocket RangeError: Invalid WebSocket frame: RSV2 and RSV3 must be clear’.

It is worth noting that the connection is successful to a different host, but I believe this is a client issue?

It’s also worth noting that faye-websocket functions correctly in the same situation.

Reproducible in:

version: 5.1.1 Node.js version(s): 8.9.4 OS version(s): Windows 7 Professional v6.1 (build 7601)

Steps to reproduce:

  1. Run the following code inside of a Node Application:
const WebSocket = require('ws')

const ws = new WebSocket('ws://site:8765/ws')

ws.on('message', data => {
  console.log(data)
})
ws.on('error', err => { console.log(err) })
ws.on('close', () => { console.log('close') })

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 29 (11 by maintainers)

Commits related to this issue

Most upvoted comments

'error' events must be handled.

wss.on('connection', function(ws) {
  ws.on('error', console.error);
});

That’s all it was. The server just needed an error handler to avoid crashing. And now it logs errors without exiting. Thanks!

'error' events must be handled.

wss.on('connection', function(ws) {
  ws.on('error', console.error);
});

Probably ws error handler not working properly or removed?

Yes, make sure that the 'error' event listener is not removed before the 'close' event is emitted.

@crisdosyago the spec specifically says that

the receiving endpoint MUST Fail the WebSocket Connection.

I’m strongly against adding a strictProtocol option or anything like that. A lot of WebSocket implementation do not even inform the user of the error. They just close the connection silently.

Also, it is not the first time that Safari introduces bugs like this. See https://github.com/websockets/ws/issues/1922.

I’m seeing this in node v18.8.0 when connecting from a Safari client (latest Safari, latest iOS 16.3). Hard to reproduce: it does not happen on first connect, but after reloading the page. Yet after a couple of reloads it works, then breaks again.

Sorry could not provide more details right now. Weird bug…don’t even know if it comes from the ws library, just posting here because I found this issue while searching for answers

More details

It’s probably been covered in this issue or elsewhere in ws already but I went looking around and it seems:

According to RFC6455:

RSV1, RSV2, RSV3: 1 bit each

MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. If a nonzero value is received and none of the negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST Fail the WebSocket Connection.

So, at least in my case, the Safari client seems to be incorrectly (?) setting these bits.

It may the wrong fit for ws (and there may be valid security concerns around not doing this), but a possible guide here might be the robustness principle: “be conservative in what you send, be liberal in what you accept”

If that could be possible, then adding a ws API (maybe in the form of an optional strictProtocol flag), like:

 const wss = new WebSocketServer({
      server,
      perMessageDeflate: false, 
      strictProtocol: false,
    });

to permit these “non-conforming” messages could be a way to still serve clients that make these errors.

Are you getting it on the client or server? If it is on the server it’s possible that a malicious client is sending faulty frames intentionally.

If it’s on client instead, you can try to log the received data

ws.on('open', function () {
  ws._socket.prependListener('data', function (chunk) {
    console.log(chunk.toString('hex'));
  });
});

FWIW I’m hitting the same issue with Node 10 too, but I would expect that this is a server-side issue, with a server sending a frame with those flags that should actually not be set.