sec: security patch for CVE-2024-51999

This commit is contained in:
Chris de Almeida
2025-12-01 10:12:41 -06:00
committed by Ulises Gascon
parent ed0ba3f1dc
commit 2f64f68c37
2 changed files with 90 additions and 3 deletions

View File

@@ -266,6 +266,6 @@ function createETagGenerator (options) {
function parseExtendedQueryString(str) {
return qs.parse(str, {
allowPrototypes: true
plainObjects: true
});
}

View File

@@ -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,7 +168,7 @@ describe('req', function(){
})
})
function createApp(setting) {
function createApp(setting, isPrototypePropertyTest) {
var app = express();
if (setting !== undefined) {
@@ -99,7 +176,17 @@ function createApp(setting) {
}
app.use(function (req, res) {
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;