diff --git a/web/workspace/src/lib/workspace/multiplexer.browser.spec.ts b/web/workspace/src/lib/workspace/multiplexer.browser.spec.ts index 23eaa7a5d..77ab8f56d 100644 --- a/web/workspace/src/lib/workspace/multiplexer.browser.spec.ts +++ b/web/workspace/src/lib/workspace/multiplexer.browser.spec.ts @@ -32,6 +32,13 @@ class FakeWebSocket { } close(code?: number, reason?: string): void { + if ( + code !== undefined && + code !== 1000 && + (code < 3000 || code > 4999) + ) { + throw new DOMException('Invalid WebSocket close code', 'InvalidAccessError'); + } this.closes.push([code, reason]); if (this.readyState === FakeWebSocket.CLOSED) return; this.readyState = FakeWebSocket.CLOSED; @@ -91,7 +98,7 @@ test('invalid inbound frame closes before dispatch and reconnects for a fresh sn ); expect(onFrame).not.toHaveBeenCalled(); - expect(first.closes).toEqual([[1002, 'Invalid workspace protocol frame']]); + expect(first.closes).toEqual([[4002, 'Invalid workspace protocol frame']]); expect(onStatus).toHaveBeenLastCalledWith('closed', 'Workspace protocol frame rejected'); expect(JSON.stringify(onStatus.mock.calls)).not.toContain('untrusted detail'); diff --git a/web/workspace/src/lib/workspace/multiplexer.ts b/web/workspace/src/lib/workspace/multiplexer.ts index a1ca52865..453aaf9d5 100644 --- a/web/workspace/src/lib/workspace/multiplexer.ts +++ b/web/workspace/src/lib/workspace/multiplexer.ts @@ -30,6 +30,7 @@ export type WorkspaceMultiplexerSubscription = { }; const multiplexers = new Map(); +const INVALID_PROTOCOL_CLOSE_CODE = 4002; let nextMultiplexerSequence = 0; function nextMultiplexerId(kind: 'client' | 'request'): string { @@ -205,7 +206,7 @@ export class WorkspaceMultiplexer { #rejectInboundFrame(): void { this.#disconnectMessage = 'Workspace protocol frame rejected'; - this.#socket?.close(1002, 'Invalid workspace protocol frame'); + this.#socket?.close(INVALID_PROTOCOL_CLOSE_CODE, 'Invalid workspace protocol frame'); } #sendWorkerMethod(clientId: string, method: Method): void {