Update dependency qs to v6.14.2 [SECURITY] - #926
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
renovate
Bot
force-pushed
the
renovate/npm-qs-vulnerability
branch
from
September 2, 2026 22:52
9faca60 to
7caf961
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
6.5.2→6.14.2qs vulnerable to Prototype Pollution
CVE-2022-24999 / GHSA-hrpp-h998-j3pp
More information
Details
qs before 6.10.3 allows attackers to cause a Node process hang because an
__ proto__key can be used. In many typical web framework use cases, an unauthenticated remote attacker can place the attack payload in the query string of the URL that is used to visit the application, such asa[__proto__]=b&a[__proto__]&a[length]=100000000. The fix was backported to qs 6.9.7, 6.8.3, 6.7.3, 6.6.1, 6.5.3, 6.4.1, 6.3.3, and 6.2.4.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion
CVE-2025-15284 / GHSA-6rw7-vpxm-498p
More information
Details
Summary
The
arrayLimitoption in qs did not enforce limits for bracket notation (a[]=1&a[]=2), only for indexed notation (a[0]=1). This is a consistency bug;arrayLimitshould apply uniformly across all array notations.Note: The default
parameterLimitof 1000 effectively mitigates the DoS scenario originally described. With default options, bracket notation cannot produce arrays larger thanparameterLimitregardless ofarrayLimit, because eacha[]=valueconsumes one parameter slot. The severity has been reduced accordingly.Details
The
arrayLimitoption only checked limits for indexed notation (a[0]=1&a[1]=2) but did not enforce it for bracket notation (a[]=1&a[]=2).Vulnerable code (
lib/parse.js:159-162):Working code (
lib/parse.js:175):The bracket notation handler at line 159 uses
utils.combine([], leaf)without validating againstoptions.arrayLimit, while indexed notation at line 175 checksindex <= options.arrayLimitbefore creating arrays.PoC
Note on parameterLimit interaction: The original advisory's "DoS demonstration" claimed a length of 10,000, but
parameterLimit(default: 1000) caps parsing to 1,000 parameters. With default options, the actual output is 1,000, not 10,000.Impact
Consistency bug in
arrayLimitenforcement. With defaultparameterLimit, the practical DoS risk is negligible sinceparameterLimitalready caps the total number of parsed parameters (and thus array elements from bracket notation). The risk increases only whenparameterLimitis explicitly set to a very high value.Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
qs's arrayLimit bypass in comma parsing allows denial of service
CVE-2026-2391 / GHSA-w7fw-mjwx-w883
More information
Details
Summary
The
arrayLimitoption in qs does not enforce limits for comma-separated values whencomma: trueis enabled, allowing attackers to cause denial-of-service via memory exhaustion. This is a bypass of the array limit enforcement, similar to the bracket notation bypass addressed in GHSA-6rw7-vpxm-498p (CVE-2025-15284).Details
When the
commaoption is set totrue(not the default, but configurable in applications), qs allows parsing comma-separated strings as arrays (e.g.,?param=a,b,cbecomes['a', 'b', 'c']). However, the limit check forarrayLimit(default: 20) and the optional throwOnLimitExceeded occur after the comma-handling logic inparseArrayValue, enabling a bypass. This permits creation of arbitrarily large arrays from a single parameter, leading to excessive memory allocation.Vulnerable code (lib/parse.js: lines ~40-50):
The
split(',')returns the array immediately, skipping the subsequent limit check. Downstream merging viautils.combinedoes not prevent allocation, even if it marks overflows for sparse arrays.This discrepancy allows attackers to send a single parameter with millions of commas (e.g.,?param=,,,,,,,,...), allocating massive arrays in memory without triggering limits. It bypasses the intent ofarrayLimit, which is enforced correctly for indexed (a[0]=) and bracket (a[]=) notations (the latter fixed in v6.14.1 per GHSA-6rw7-vpxm-498p).PoC
Test 1 - Basic bypass:
Configuration:
comma: truearrayLimit: 5throwOnLimitExceeded: trueExpected: Throws "Array limit exceeded" error.
Actual: Parses successfully, creating an array of length 26.
Impact
Denial of Service (DoS) via memory exhaustion.
Suggested Fix
Move the
arrayLimitcheck before the comma split inparseArrayValue, and enforce it on the resulting array length. UsecurrentArrayLength(already calculated upstream) for consistency with bracket notation fixes.Current code (lib/parse.js: lines ~40-50):
Fixed code:
This aligns behavior with indexed and bracket notations, reuses
currentArrayLength, and respectsthrowOnLimitExceeded. Update README to note the consistent enforcement.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
ljharb/qs (qs)
v6.14.2Compare Source
parse: mark overflow objects for indexed notation exceedingarrayLimit(#546)arrayLimitmeans max count, not max index, incombine/merge/parseArrayValueparse: throw onarrayLimitexceeded with indexed notation whenthrowOnLimitExceededis true (#529)parse: enforcearrayLimitoncomma-parsed valuesparse: fix error message to reflect arrayLimit as max index; remove extraneous comments (#545).push, usevoidaddQueryPrefixdoes not add?to empty output (#418)parseArraysandarrayLimitdocumentation (#543)arrayLength→arrayLimit)v6.14.1Compare Source
arrayLimitapplies to[]notation as wellparse: when a custom decoder returnsnullfor a key, ignore that keyparse: extract key segment splitting helperstringify: increase coverageeslint,@ljharb/eslint-config,npmignore,es-value-fixtures,for-each,object-inspectv6.14.0Compare Source
parse: addthrowOnParameterLimitExceededoption (#517)parse: useutils.combinemoreparse: add explicitthrowOnLimitExceededdefaultside-channeles-value-fixtures,has-bigints,has-proto,has-symbolsv6.13.3Compare Source
[Fix] fix regressions from robustness refactor
[actions] update reusable workflows
v6.13.2Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.13.1Compare Source
stringify: avoid a crash when afilterkey isnullutils.merge: functions should not be stringified into keysparse: avoid a crash with interpretNumericEntities: true, comma: true, and iso charsetstringify: ensure a non-stringfilterdoes not crash__proto__syntax instead ofObject.createfor null objectsutils.merge: add some coveragees-value-fixtures,mock-property,object-inspect,tapev6.13.0Compare Source
parse: addstrictDepthoption (#511)npm auditinstead ofaudv6.12.5Compare Source
v6.12.4Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.12.3Compare Source
parse: properly account forstrictNullHandlingwhenallowEmptyArraysv6.12.2Compare Source
parse: parse encoded square brackets (#506)v6.12.1Compare Source
parse: DisabledecodeDotInKeysby default to restore previous behavior (#501)utils: Optimize performance under large data volumes, reduce memory usage, and speed up processing (#502)utils: use+=v6.12.0Compare Source
parse/stringify: adddecodeDotInKeys/encodeDotKeysoptions (#488)parse: addduplicatesoptionparse/stringify: addallowEmptyArraysoption to allow [] in object values (#487)parse/stringify: move allowDots config logic to its own variablestringify: move option-handling code intonormalizeStringifyOptionsstringify: clarify defaultarrayFormatbehaviorside-channelsideEffectsflagparse: remove useless tests; add coveragestringify: increase coveragemock-propertystringify: improve coverage@ljharb/eslint-config,aud,has-override-mistake,has-property-descriptors,mock-property,npmignore,object-inspect,tapeglob, since v10.3.8+ requires a brokenjackspeakjackspeaksince 2.1.2+ depends on npm aliases, which kill the install process in npm < 6v6.11.4Compare Source
v6.11.3Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.11.2Compare Source
parse: Fix parsing when the global Object prototype is frozen (#473)v6.11.1Compare Source
stringify: encode comma values more consistently (#463)filteroption for injecting custom serialization, i.e. of custom types (#447)@ljharb/eslint-config,aud,object-inspect,tapev6.11.0Compare Source
stringify: revert0e903c0; addcommaRoundTripoption (#442)v6.10.7Compare Source
v6.10.6Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.10.5Compare Source
stringify: witharrayFormat: comma, properly include an explicit[]on a single-item array (#434)v6.10.4Compare Source
stringify: witharrayFormat: comma, include an explicit[]on a single-item array (#441)npmignoreto autogenerate an npmignore fileeslint,@ljharb/eslint-config,aud,has-symbol,object-inspect,tapev6.10.3Compare Source
parse: ignore__proto__keys (#428)stringify: avoid relying on a globalundefined(#427)eslint,@ljharb/eslint-config,object-inspect,tapev6.10.2Compare Source
stringify: actually fix cyclic references (#426)stringify: avoid encoding arrayformat comma whenencodeValuesOnly = true(#424)eslint,@ljharb/eslint-config,aud,object-inspect,safe-publish-latest,tapev6.10.1Compare Source
stringify: avoid exception on repeated object values (#402)v6.10.0Compare Source
stringify: throw on cycles, instead of an infinite loop (#395, #394, #393)parse: addallowSparseoption for collapsing arrays with missing indices (#312)npm run distin publish, not installeslint,@ljharb/eslint-config,aud,has-symbols,tapeljharb/actions/node/installinstead ofljharb/actions/node/runv6.9.9Compare Source
npmignoreto autogenerate an npmignore filev6.9.8Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.9.7Compare Source
parse: ignore__proto__keys (#428)stringify: avoid encoding arrayformat comma whenencodeValuesOnly = true(#424)stringify: avoid relying on a globalundefined(#427)v6.9.6Compare Source
distdir; mistakenly removed ind4f6c32v6.9.5Compare Source
stringify: do not encode parens for RFC1738stringify: fix arrayFormat comma with empty array/objects (#350)format: removeutil.assigncallpull_request_targeteventstringify: add tests for #378nycon all tests; usetaperunnereslint,@ljharb/eslint-config,browserify,mkdirp,object-inspect,tape; addaudv6.9.4Compare Source
stringify: whenarrayFormatiscomma, respectserializeDate(#364)stringify: reduce branching (part of #350)maybeMaptoutilsbrowserify,tapev6.9.3Compare Source
v6.9.2Compare Source
parse: Fix parsing array from object withcommatrue (#359)parse: throw a TypeError instead of an Error for bad charset (#349)eslint,@ljharb/eslint-config,object-inspect,has-symbols,tape,mkdirp,iconv-litev6.9.1Compare Source
parse: with comma true, handle field that holds an array of arrays (#335)parse: with comma true, do not split non-string values (#334)fundingfieldeslint,@ljharb/eslint-configv6.9.0Compare Source
parse/stringify: Pass extra key/value argument todecoder(#333)eslint,@ljharb/eslint-config,evalmdparse: add passingarrayFormattestsposttestusingnpx audto runnpm auditwithout a lockfilenodev12.10,v11.15,v10.16,v8.16Buffer.fromin node v5.0-v5.9 and v4.0-v4.4 requires a TypedArrayv6.8.5Compare Source
npmignoreto autogenerate an npmignore filev6.8.4Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.8.3Compare Source
parse: ignore__proto__keys (#428)stringify: avoid relying on a globalundefined(#427)stringify: avoid encoding arrayformat comma whenencodeValuesOnly = true(#424)stringify: reduce branchingv6.8.2Compare Source
v6.8.1Compare Source
parse: Fix parsing array from object withcommatrue (#359)parse: throw a TypeError instead of an Error for bad charset (#349)parse: with comma true, handle field that holds an array of arrays (#335)parse: with comma true, do not split non-string values (#334)fundingfieldeslint,@ljharb/eslint-config,tape,safe-publish-latest,evalmd,has-symbols,iconv-lite,mkdirp,object-inspectparse: add passingarrayFormattestsBuffer.fromin node v5.0-v5.9 and v4.0-v4.4 requires a TypedArrayv6.8.0Compare Source
depth=falseto preserve the original key; [Fix]depth=0should preserve the original key (#326)formats: tiny bit of cleanup.eslint,@ljharb/eslint-config,browserify,safe-publish-latest,iconv-lite,tapedepth=0anddepth=falsebehavior, both current and intuitive/intended (#326)eclintinstead ofeditorconfig-toolsv6.7.5Compare Source
npmignoreto autogenerate an npmignore filev6.7.4Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.7.3Compare Source
parse: ignore__proto__keys (#428)stringify: avoid encoding arrayformat comma whenencodeValuesOnly = true(#424)stringify: avoid relying on a globalundefined(#427)nycfor coveragev6.7.2Compare Source
v6.7.1Compare Source
parse: Fix parsing array from object withcommatrue (#359)parse: with comma true, handle field that holds an array of arrays (#335)parse: with comma true, do not split non-string values (#334)parse: throw a TypeError instead of an Error for bad charset (#349)formats: tiny bit of cleanup.fundingfieldeslint,@ljharb/eslint-config,tape,safe-publish-latest,evalmd,iconv-lite,mkdirp,object-inspect,browserifyparse: add passingarrayFormattestsBuffer.fromin node v5.0-v5.9 and v4.0-v4.4 requires a TypedArraydepth=0anddepth=falsebehavior, both current and intuitive/intendedeclintinstead ofeditorconfig-toolsv6.7.0Compare Source
stringify/parse: addcommaas anarrayFormatoption (#276, #219)utils.merge: avoid a crash with a null target and a truthy non-array source, also with an array sourcestringify: cacheObject.prototype.hasOwnPropertyutils:isBuffer: small tweak; add testsArray.isArrayparse/stringify: make a function to normalize the optionsutils: reduce observable [[Get]]sstringify/utils: cacheArray.isArrayString(x)overx.toString()v6.6.3Compare Source
npmignoreto autogenerate an npmignore filev6.6.2Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.6.1Compare Source
parse: ignore__proto__keys (#428)utils.merge: avoid a crash with a null target and an array sourceutils.merge: avoid a crash with a null target and a truthy non-array sourcestringify: avoid relying on a globalundefined(#427)stringify: cacheObject.prototype.hasOwnPropertyformats: tiny bit of cleanup.utils:isBuffer: small tweak; add testsstringify/utils: cacheArray.isArrayutils: reduce observable [[Get]]sArray.isArrayparse/stringify: make a function to normalize the optionsString(x)overx.toString()v6.6.0Compare Source
utilsfunction (#189)stringify: fix a crash withstrictNullHandlingand a customfilter/serializeDate(#279)parseArraysis false, properly handle keys ending in[](#260)stringify: do not crash in an obscure combo ofinterpretNumericEntities, a bad customdecoder, &iso-8859-1utils:merge: fix crash whensourceis a truthy primitive & no options are providedstringify: Avoid arr = arr.concat(...), push to the existing instance (#269)parse: only need to reassign the var onceparse/stringify: clean upcharsetoptions checking; fix defaultsparse: one lessconcatcallutils:compactQueue: make it explicitly side-effectingbrowserify,eslint,@ljharb/eslint-config,iconv-lite,safe-publish-latest,tapenodev10.10,v9.11,v8.12,v6.14,v4.9; pin included builds to LTSv6.5.5Compare Source
npmignoreto autogenerate an npmignore filev6.5.4Compare Source
.push, usevoidparseArraysandarrayLimitdocumentation (#543)addQueryPrefixdoes not add?to empty output (#418)v6.5.3Compare Source
parse: ignore__proto__keys (#428)utils.merge: avoid a crash with a null target and a truthy non-array sourcestringify: fix a crash withstrictNullHandlingand a customfilter/serializeDate(#279)utils:merge: fix crash whensourceis a truthy primitive & no options are providedparseArraysis false, properly handle keys ending in[]utils.merge: avoid a crash with a null target and an array sourceutils: reduce observable [[Get]]sArray.isArraystringify: Avoid arr = arr.concat(...), push to the existing instance (#269)parse: only need to reassign the var oncestringify: avoid relying on a globalundefined(#427)String(x)overx.toString()Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.