VYPR
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.

PackageAffected versionsPatched versions
expressnpm
< 4.22.04.22.0
expressnpm
>= 5.0.0, < 5.2.05.2.0

Affected products

1

Patches

1
2f64f68c37c6

sec: security patch for CVE-2024-51999

https://github.com/expressjs/expressChris de AlmeidaDec 1, 2025via ghsa
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

News mentions

0

No linked articles in our index yet.