Skip to content

Commit 724d328

Browse files
committed
fix: treat invalid/reserved close codes as 1000
1 parent 155386e commit 724d328

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

lib/client.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const { getErrorPlainObject, createRPCError, getPackageIdent } = require('./util
1111
const Queue = require('./queue');
1212
const EventBuffer = require('./event-buffer');
1313
const standardValidators = require('./standard-validators');
14+
const {isValidStatusCode} = require('./ws-util');
1415

1516
const MSG_CALL = 2;
1617
const MSG_CALLRESULT = 3;
@@ -212,7 +213,10 @@ class RPCClient extends EventEmitter {
212213
} else {
213214
// await pending calls & responses
214215
await this._awaitUntilPendingSettled();
215-
this._ws.close(code ?? 1000, reason);
216+
if (!code || !isValidStatusCode(code)) {
217+
code = 1000;
218+
}
219+
this._ws.close(code, reason);
216220
}
217221

218222
let [codeRes, reasonRes] = await once(this._ws, 'close');

lib/ws-util.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,26 @@ function parseSubprotocols(header) {
108108
return protocols;
109109
}
110110

111+
/**
112+
* Checks if a status code is allowed in a close frame.
113+
*
114+
* @param {Number} code The status code
115+
* @return {Boolean} `true` if the status code is valid, else `false`
116+
* @public
117+
*/
118+
function isValidStatusCode(code) {
119+
return (
120+
(code >= 1000 &&
121+
code <= 1014 &&
122+
code !== 1004 &&
123+
code !== 1005 &&
124+
code !== 1006) ||
125+
(code >= 3000 && code <= 4999)
126+
);
127+
}
128+
111129
module.exports = {
112130
abortHandshake,
113131
parseSubprotocols,
132+
isValidStatusCode,
114133
};

test/client.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,30 @@ describe('RPCClient', function(){
888888

889889
});
890890

891+
it('should treat invalid/reserved close codes as 1000', async () => {
892+
893+
const {server, endpoint, close} = await createServer();
894+
const cli = new RPCClient({endpoint, identity: 'X'});
895+
896+
try {
897+
const testCodes = [-1000,0,1,1005,10000];
898+
899+
for (const testCode of testCodes) {
900+
const serverClientPromise = once(server, 'client');
901+
await cli.connect();
902+
const [serverClient] = await serverClientPromise;
903+
const serverClosePromise = once(serverClient, 'close');
904+
await cli.close({code: testCode});
905+
const [serverClose] = await serverClosePromise;
906+
assert.equal(serverClose.code, 1000);
907+
}
908+
909+
} finally {
910+
close();
911+
}
912+
913+
});
914+
891915
it('should return the close code of the first close() call', async () => {
892916

893917
const {endpoint, close} = await createServer();

0 commit comments

Comments
 (0)