From 3d7890056e6582c8214bedfbf659cfe0bc98b61a Mon Sep 17 00:00:00 2001 From: virtual machine Date: Fri, 20 Mar 2026 20:49:43 -0500 Subject: [PATCH] Fix query parameter truncation with configurable limit - Change default query parser from 'simple' to 'extended' - Add 'query parser limit' setting with default of 10000 - Pass limit to query parser at parse time (not compile time) - Fixes issue #5878 - query params truncated at 1000+ params - Supersedes PR #7116 which used Infinity (security concern) --- lib/application.js | 3 ++- lib/request.js | 7 +++++++ lib/utils.js | 6 ++++-- test/req.query.js | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/application.js b/lib/application.js index 47be2a20c1a..07771fe153e 100644 --- a/lib/application.js +++ b/lib/application.js @@ -94,7 +94,8 @@ app.defaultConfiguration = function defaultConfiguration() { this.enable('x-powered-by'); this.set('etag', 'weak'); this.set('env', env); - this.set('query parser', 'simple') + this.set('query parser', 'extended') + this.set('query parser limit', 10000) this.set('subdomain offset', 2); this.set('trust proxy', false); diff --git a/lib/request.js b/lib/request.js index e7a451df6d9..7b02f1780dd 100644 --- a/lib/request.js +++ b/lib/request.js @@ -21,6 +21,7 @@ var fresh = require('fresh'); var parseRange = require('range-parser'); var parse = require('parseurl'); var proxyaddr = require('proxy-addr'); +var utils = require('./utils'); /** * Request prototype. @@ -229,6 +230,7 @@ req.range = function range(size, options) { defineGetter(req, 'query', function query(){ var queryparse = this.app.get('query parser fn'); + var limit = this.app.get('query parser limit'); if (!queryparse) { // parsing is disabled @@ -237,6 +239,11 @@ defineGetter(req, 'query', function query(){ var querystring = parse(this).query; + // Pass limit to extended parser + if (queryparse === utils.parseExtendedQueryString) { + return queryparse(querystring, limit); + } + return queryparse(querystring); }); diff --git a/lib/utils.js b/lib/utils.js index 4f21e7ef1e3..4735a495cf5 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -264,8 +264,10 @@ function createETagGenerator (options) { * @private */ -function parseExtendedQueryString(str) { +function parseExtendedQueryString(str, limit) { return qs.parse(str, { - allowPrototypes: true + allowPrototypes: true, + parameterLimit: limit || 10000 }); } +exports.parseExtendedQueryString = parseExtendedQueryString; diff --git a/test/req.query.js b/test/req.query.js index c0d3c8376e9..60cb8a29274 100644 --- a/test/req.query.js +++ b/test/req.query.js @@ -14,12 +14,12 @@ describe('req', function(){ .expect(200, '{}', done); }); - it('should default to parse simple keys', function (done) { + it('should default to parse extended keys', function (done) { var app = createApp(); request(app) .get('/?user[name]=tj') - .expect(200, '{"user[name]":"tj"}', done); + .expect(200, '{"user":{"name":"tj"}}', done); }); describe('when "query parser" is extended', function () {