Low severityOSV Advisory· Published Dec 1, 2025· Updated Dec 2, 2025
CVE-2024-51999
CVE-2024-51999
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
expressnpm | < 4.22.0 | 4.22.0 |
expressnpm | >= 5.0.0, < 5.2.0 | 5.2.0 |
Affected products
1Patches
12f64f68c37c6sec: security patch for CVE-2024-51999
2 files changed · +90 −3
lib/utils.js+1 −1 modified@@ -266,6 +266,6 @@ function createETagGenerator (options) { function parseExtendedQueryString(str) { return qs.parse(str, { - allowPrototypes: true + plainObjects: true }); }
test/req.query.js+89 −2 modified@@ -3,6 +3,7 @@ var assert = require('node:assert') var express = require('../') , request = require('supertest'); +var qs = require('qs'); describe('req', function(){ describe('.query', function(){ @@ -38,6 +39,22 @@ describe('req', function(){ .get('/?user.name=tj') .expect(200, '{"user.name":"tj"}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" is simple', function () { @@ -48,6 +65,22 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('simple', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('simple', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" is a function', function () { @@ -60,6 +93,18 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"length":17}', done); }); + + // test exists to verify behavior for folks wishing to workaround our qs defaults + it('should drop object prototype property names and be able to access object prototype properties', function (done) { + var app = createApp( + function (str) { + return qs.parse(str) + }, true); + + request(app) + .get('/?hasOwnProperty=biscuits') + .expect(200, '{"query":{},"hasOwnProperty":false}', done); + }); }); describe('when "query parser" disabled', function () { @@ -70,6 +115,22 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" enabled', function () { @@ -80,6 +141,22 @@ describe('req', function(){ .get('/?user%5Bname%5D=tj') .expect(200, '{"user[name]":"tj"}', done); }); + + it('should not be able to access object prototype properties', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?foo=yee') + .expect(200, /TypeError: req\.query\.hasOwnProperty is not a function/, done); + }); + + it('should be able to use object prototype property names as keys', function (done) { + var app = createApp('extended', true); + + request(app) + .get('/?hasOwnProperty=yee') + .expect(200, '{"query":{"hasOwnProperty":"yee"},"error":"TypeError: req.query.hasOwnProperty is not a function"}', done); + }); }); describe('when "query parser" an unknown value', function () { @@ -91,15 +168,25 @@ describe('req', function(){ }) }) -function createApp(setting) { +function createApp(setting, isPrototypePropertyTest) { var app = express(); if (setting !== undefined) { app.set('query parser', setting); } app.use(function (req, res) { - res.send(req.query); + if(isPrototypePropertyTest) { + try { + var hasOwnProperty = req.query.hasOwnProperty('✨ express ✨'); + res.send({ query: req.query, hasOwnProperty: hasOwnProperty }); + } catch (error) { + res.send({ query: req.query, error: error.toString() }); + } + } + else { + res.send(req.query); + } }); return app;
Vulnerability mechanics
Not enough inputs (no patches or CWE) to synthesize mechanics for this CVE.
References
6- github.com/advisories/GHSA-pj86-cfqh-vqx6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-51999ghsaADVISORY
- github.com/expressjs/express/commit/2f64f68c37c64ae333e41ff38032d21860f22255ghsaWEB
- github.com/expressjs/express/releases/tag/4.22.0ghsaWEB
- github.com/expressjs/express/releases/tag/v5.2.0ghsaWEB
- github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6ghsaWEB
News mentions
0No linked articles in our index yet.