diff --git a/lib/web/websocket/connection.js b/lib/web/websocket/connection.js index 5058fc58095..85b471e6e0b 100644 --- a/lib/web/websocket/connection.js +++ b/lib/web/websocket/connection.js @@ -261,13 +261,9 @@ function closeWebSocketConnection (ws, code, reason, reasonByteLength) { /** @type {import('stream').Duplex} */ const socket = ws[kResponse].socket - socket.write(frame.createFrame(opcodes.CLOSE), (err) => { - if (!err) { - ws[kSentClose] = sentCloseFrameState.SENT - } - }) + socket.write(frame.createFrame(opcodes.CLOSE)) - ws[kSentClose] = sentCloseFrameState.PROCESSING + ws[kSentClose] = sentCloseFrameState.SENT // Upon either sending or receiving a Close control frame, it is said // that _The WebSocket Closing Handshake is Started_ and that the diff --git a/lib/web/websocket/receiver.js b/lib/web/websocket/receiver.js index 087b962a3ce..20ced08b951 100644 --- a/lib/web/websocket/receiver.js +++ b/lib/web/websocket/receiver.js @@ -5,7 +5,15 @@ const assert = require('node:assert') const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require('./constants') const { kReadyState, kSentClose, kResponse, kReceivedClose } = require('./symbols') const { channels } = require('../../core/diagnostics') -const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived, utf8Decode, isControlFrame, isContinuationFrame } = require('./util') +const { + isValidStatusCode, + isValidOpcode, + failWebsocketConnection, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isContinuationFrame +} = require('./util') const { WebsocketFrameSend } = require('./frame') const { CloseEvent } = require('./events') @@ -58,6 +66,11 @@ class ByteParser extends Writable { const opcode = buffer[0] & 0x0F const masked = (buffer[1] & 0x80) === 0x80 + if (!isValidOpcode(opcode)) { + failWebsocketConnection(this.ws, 'Invalid opcode received') + return callback() + } + if (masked) { failWebsocketConnection(this.ws, 'Frame cannot be masked') return callback() diff --git a/lib/web/websocket/util.js b/lib/web/websocket/util.js index 35d67d17eb5..ea5b29d3549 100644 --- a/lib/web/websocket/util.js +++ b/lib/web/websocket/util.js @@ -226,6 +226,14 @@ function isContinuationFrame (opcode) { return opcode === opcodes.CONTINUATION } +function isTextBinaryFrame (opcode) { + return opcode === opcodes.TEXT || opcode === opcodes.BINARY +} + +function isValidOpcode (opcode) { + return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode) +} + // https://nodejs.org/api/intl.html#detecting-internationalization-support const hasIntl = typeof process.versions.icu === 'string' const fatalDecoder = hasIntl ? new TextDecoder('utf-8', { fatal: true }) : undefined @@ -255,5 +263,7 @@ module.exports = { websocketMessageReceived, utf8Decode, isControlFrame, - isContinuationFrame + isContinuationFrame, + isTextBinaryFrame, + isValidOpcode }