VYPR
High severity7.5NVD Advisory· Published Jun 17, 2024· Updated Apr 15, 2026

CVE-2024-37890

CVE-2024-37890

Description

ws is an open source WebSocket client and server for Node.js. A request with a number of headers exceeding theserver.maxHeadersCount threshold could be used to crash a ws server. The vulnerability was fixed in ws@8.17.1 (e55e510) and backported to ws@7.5.10 (22c2876), ws@6.2.3 (eeb76d3), and ws@5.2.4 (4abd8f6). In vulnerable versions of ws, the issue can be mitigated in the following ways: 1. Reduce the maximum allowed length of the request headers using the --max-http-header-size=size and/or the maxHeaderSize options so that no more headers than the server.maxHeadersCount limit can be sent. 2. Set server.maxHeadersCount to 0 so that no limit is applied.

Patches

4
22c28763234a

[security] Fix crash when the Upgrade header cannot be read (#2231)

https://github.com/websockets/wsLuigi PincaJun 16, 2024via ghsa
4 files changed · +73 2
  • lib/websocket.js+3 1 modified
    @@ -799,7 +799,9 @@ function initAsClient(websocket, address, protocols, options) {
     
         req = websocket._req = null;
     
    -    if (res.headers.upgrade.toLowerCase() !== 'websocket') {
    +    const upgrade = res.headers.upgrade;
    +
    +    if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
           abortHandshake(websocket, socket, 'Invalid Upgrade header');
           return;
         }
    
  • lib/websocket-server.js+3 1 modified
    @@ -210,12 +210,14 @@ class WebSocketServer extends EventEmitter {
           req.headers['sec-websocket-key'] !== undefined
             ? req.headers['sec-websocket-key'].trim()
             : false;
    +    const upgrade = req.headers.upgrade;
         const version = +req.headers['sec-websocket-version'];
         const extensions = {};
     
         if (
           req.method !== 'GET' ||
    -      req.headers.upgrade.toLowerCase() !== 'websocket' ||
    +      upgrade === undefined ||
    +      upgrade.toLowerCase() !== 'websocket' ||
           !key ||
           !keyRegex.test(key) ||
           (version !== 8 && version !== 13) ||
    
  • test/websocket-server.test.js+41 0 modified
    @@ -494,6 +494,47 @@ describe('WebSocketServer', () => {
       });
     
       describe('Connection establishing', () => {
    +    it('fails if the Upgrade header field value cannot be read', (done) => {
    +      const server = http.createServer();
    +      const wss = new WebSocket.Server({ noServer: true });
    +
    +      server.maxHeadersCount = 1;
    +
    +      server.on('upgrade', (req, socket, head) => {
    +        assert.deepStrictEqual(req.headers, { foo: 'bar' });
    +        wss.handleUpgrade(req, socket, head, () => {
    +          done(new Error('Unexpected callback invocation'));
    +        });
    +      });
    +
    +      server.listen(() => {
    +        const req = http.get({
    +          port: server.address().port,
    +          headers: {
    +            foo: 'bar',
    +            bar: 'baz',
    +            Connection: 'Upgrade',
    +            Upgrade: 'websocket'
    +          }
    +        });
    +
    +        req.on('response', (res) => {
    +          assert.strictEqual(res.statusCode, 400);
    +
    +          const chunks = [];
    +
    +          res.on('data', (chunk) => {
    +            chunks.push(chunk);
    +          });
    +
    +          res.on('end', () => {
    +            assert.strictEqual(Buffer.concat(chunks).toString(), 'Bad Request');
    +            server.close(done);
    +          });
    +        });
    +      });
    +    });
    +
         it('fails if the Sec-WebSocket-Key header is invalid (1/2)', (done) => {
           const wss = new WebSocket.Server({ port: 0 }, () => {
             const req = http.get({
    
  • test/websocket.test.js+26 0 modified
    @@ -528,6 +528,32 @@ describe('WebSocket', () => {
         beforeEach((done) => server.listen(0, done));
         afterEach((done) => server.close(done));
     
    +    it('fails if the Upgrade header field value cannot be read', (done) => {
    +      server.once('upgrade', (req, socket) => {
    +        socket.on('end', socket.end);
    +        socket.write(
    +          'HTTP/1.1 101 Switching Protocols\r\n' +
    +            'Connection: Upgrade\r\n' +
    +            'Upgrade: websocket\r\n' +
    +            '\r\n'
    +        );
    +      });
    +
    +      const ws = new WebSocket(`ws://localhost:${server.address().port}`);
    +
    +      ws._req.maxHeadersCount = 1;
    +
    +      ws.on('upgrade', (res) => {
    +        assert.deepStrictEqual(res.headers, { connection: 'Upgrade' });
    +
    +        ws.on('error', (err) => {
    +          assert.ok(err instanceof Error);
    +          assert.strictEqual(err.message, 'Invalid Upgrade header');
    +          done();
    +        });
    +      });
    +    });
    +
         it('fails if the Upgrade header field value is not "websocket"', (done) => {
           server.once('upgrade', (req, socket) => {
             socket.on('end', socket.end);
    
eeb76d313e2a

[security] Fix crash when the Upgrade header cannot be read (#2231)

https://github.com/websockets/wsLuigi PincaJun 16, 2024via ghsa
2 files changed · +44 1
  • lib/websocket-server.js+3 1 modified
    @@ -186,12 +186,14 @@ class WebSocketServer extends EventEmitter {
           req.headers['sec-websocket-key'] !== undefined
             ? req.headers['sec-websocket-key'].trim()
             : false;
    +    const upgrade = req.headers.upgrade;
         const version = +req.headers['sec-websocket-version'];
         const extensions = {};
     
         if (
           req.method !== 'GET' ||
    -      req.headers.upgrade.toLowerCase() !== 'websocket' ||
    +      upgrade === undefined ||
    +      upgrade.toLowerCase() !== 'websocket' ||
           !key ||
           !keyRegex.test(key) ||
           (version !== 8 && version !== 13) ||
    
  • test/websocket-server.test.js+41 0 modified
    @@ -383,6 +383,47 @@ describe('WebSocketServer', () => {
       });
     
       describe('Connection establishing', () => {
    +    it('fails if the Upgrade header field value cannot be read', (done) => {
    +      const server = http.createServer();
    +      const wss = new WebSocket.Server({ noServer: true });
    +
    +      server.maxHeadersCount = 1;
    +
    +      server.on('upgrade', (req, socket, head) => {
    +        assert.deepStrictEqual(req.headers, { foo: 'bar' });
    +        wss.handleUpgrade(req, socket, head, () => {
    +          done(new Error('Unexpected callback invocation'));
    +        });
    +      });
    +
    +      server.listen(() => {
    +        const req = http.get({
    +          port: server.address().port,
    +          headers: {
    +            foo: 'bar',
    +            bar: 'baz',
    +            Connection: 'Upgrade',
    +            Upgrade: 'websocket'
    +          }
    +        });
    +
    +        req.on('response', (res) => {
    +          assert.strictEqual(res.statusCode, 400);
    +
    +          const chunks = [];
    +
    +          res.on('data', (chunk) => {
    +            chunks.push(chunk);
    +          });
    +
    +          res.on('end', () => {
    +            assert.strictEqual(Buffer.concat(chunks).toString(), 'Bad Request');
    +            server.close(done);
    +          });
    +        });
    +      });
    +    });
    +
         it('fails if the Sec-WebSocket-Key header is invalid (1/2)', (done) => {
           const wss = new WebSocket.Server({ port: 0 }, () => {
             const req = http.get({
    
4abd8f6de4b0

[security] Fix crash when the Upgrade header cannot be read (#2231)

https://github.com/websockets/wsLuigi PincaJun 16, 2024via ghsa
2 files changed · +44 1
  • lib/websocket-server.js+3 1 modified
    @@ -161,11 +161,13 @@ class WebSocketServer extends EventEmitter {
       handleUpgrade (req, socket, head, cb) {
         socket.on('error', socketOnError);
     
    +    const upgrade = req.headers.upgrade;
         const version = +req.headers['sec-websocket-version'];
         const extensions = {};
     
         if (
    -      req.method !== 'GET' || req.headers.upgrade.toLowerCase() !== 'websocket' ||
    +      req.method !== 'GET' || upgrade === undefined ||
    +      upgrade.toLowerCase() !== 'websocket' ||
           !req.headers['sec-websocket-key'] || (version !== 8 && version !== 13) ||
           !this.shouldHandle(req)
         ) {
    
  • test/websocket-server.test.js+41 0 modified
    @@ -364,6 +364,47 @@ describe('WebSocketServer', function () {
       });
     
       describe('Connection establishing', function () {
    +    it('fails if the Upgrade header field value cannot be read', (done) => {
    +      const server = http.createServer();
    +      const wss = new WebSocket.Server({ noServer: true });
    +
    +      server.maxHeadersCount = 1;
    +
    +      server.on('upgrade', (req, socket, head) => {
    +        assert.deepStrictEqual(req.headers, { foo: 'bar' });
    +        wss.handleUpgrade(req, socket, head, () => {
    +          done(new Error('Unexpected callback invocation'));
    +        });
    +      });
    +
    +      server.listen(() => {
    +        const req = http.get({
    +          port: server.address().port,
    +          headers: {
    +            foo: 'bar',
    +            bar: 'baz',
    +            Connection: 'Upgrade',
    +            Upgrade: 'websocket'
    +          }
    +        });
    +
    +        req.on('response', (res) => {
    +          assert.strictEqual(res.statusCode, 400);
    +
    +          const chunks = [];
    +
    +          res.on('data', (chunk) => {
    +            chunks.push(chunk);
    +          });
    +
    +          res.on('end', () => {
    +            assert.strictEqual(Buffer.concat(chunks).toString(), 'Bad Request');
    +            server.close(done);
    +          });
    +        });
    +      });
    +    });
    +
         it('fails if the Sec-WebSocket-Key header is invalid', function (done) {
           const wss = new WebSocket.Server({ port: 0 }, () => {
             const req = http.get({
    
e55e5106f10f

[security] Fix crash when the Upgrade header cannot be read (#2231)

https://github.com/websockets/wsLuigi PincaJun 16, 2024via ghsa
4 files changed · +76 3
  • lib/websocket.js+3 1 modified
    @@ -928,7 +928,9 @@ function initAsClient(websocket, address, protocols, options) {
     
         req = websocket._req = null;
     
    -    if (res.headers.upgrade.toLowerCase() !== 'websocket') {
    +    const upgrade = res.headers.upgrade;
    +
    +    if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
           abortHandshake(websocket, socket, 'Invalid Upgrade header');
           return;
         }
    
  • lib/websocket-server.js+3 2 modified
    @@ -235,6 +235,7 @@ class WebSocketServer extends EventEmitter {
         socket.on('error', socketOnError);
     
         const key = req.headers['sec-websocket-key'];
    +    const upgrade = req.headers.upgrade;
         const version = +req.headers['sec-websocket-version'];
     
         if (req.method !== 'GET') {
    @@ -243,13 +244,13 @@ class WebSocketServer extends EventEmitter {
           return;
         }
     
    -    if (req.headers.upgrade.toLowerCase() !== 'websocket') {
    +    if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
           const message = 'Invalid Upgrade header';
           abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
           return;
         }
     
    -    if (!key || !keyRegex.test(key)) {
    +    if (key === undefined || !keyRegex.test(key)) {
           const message = 'Missing or invalid Sec-WebSocket-Key header';
           abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
           return;
    
  • test/websocket-server.test.js+44 0 modified
    @@ -653,6 +653,50 @@ describe('WebSocketServer', () => {
           });
         });
     
    +    it('fails if the Upgrade header field value cannot be read', (done) => {
    +      const server = http.createServer();
    +      const wss = new WebSocket.Server({ noServer: true });
    +
    +      server.maxHeadersCount = 1;
    +
    +      server.on('upgrade', (req, socket, head) => {
    +        assert.deepStrictEqual(req.headers, { foo: 'bar' });
    +        wss.handleUpgrade(req, socket, head, () => {
    +          done(new Error('Unexpected callback invocation'));
    +        });
    +      });
    +
    +      server.listen(() => {
    +        const req = http.get({
    +          port: server.address().port,
    +          headers: {
    +            foo: 'bar',
    +            bar: 'baz',
    +            Connection: 'Upgrade',
    +            Upgrade: 'websocket'
    +          }
    +        });
    +
    +        req.on('response', (res) => {
    +          assert.strictEqual(res.statusCode, 400);
    +
    +          const chunks = [];
    +
    +          res.on('data', (chunk) => {
    +            chunks.push(chunk);
    +          });
    +
    +          res.on('end', () => {
    +            assert.strictEqual(
    +              Buffer.concat(chunks).toString(),
    +              'Invalid Upgrade header'
    +            );
    +            server.close(done);
    +          });
    +        });
    +      });
    +    });
    +
         it('fails if the Upgrade header field value is not "websocket"', (done) => {
           const wss = new WebSocket.Server({ port: 0 }, () => {
             const req = http.get({
    
  • test/websocket.test.js+26 0 modified
    @@ -757,6 +757,32 @@ describe('WebSocket', () => {
         beforeEach((done) => server.listen(0, done));
         afterEach((done) => server.close(done));
     
    +    it('fails if the Upgrade header field value cannot be read', (done) => {
    +      server.once('upgrade', (req, socket) => {
    +        socket.on('end', socket.end);
    +        socket.write(
    +          'HTTP/1.1 101 Switching Protocols\r\n' +
    +            'Connection: Upgrade\r\n' +
    +            'Upgrade: websocket\r\n' +
    +            '\r\n'
    +        );
    +      });
    +
    +      const ws = new WebSocket(`ws://localhost:${server.address().port}`);
    +
    +      ws._req.maxHeadersCount = 1;
    +
    +      ws.on('upgrade', (res) => {
    +        assert.deepStrictEqual(res.headers, { connection: 'Upgrade' });
    +
    +        ws.on('error', (err) => {
    +          assert.ok(err instanceof Error);
    +          assert.strictEqual(err.message, 'Invalid Upgrade header');
    +          done();
    +        });
    +      });
    +    });
    +
         it('fails if the Upgrade header field value is not "websocket"', (done) => {
           server.once('upgrade', (req, socket) => {
             socket.on('end', socket.end);
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

9

News mentions

0

No linked articles in our index yet.