chore(deps): update dependency qs to v6.15.2 [security]#958
Open
renovate[bot] wants to merge 1 commit into
Open
chore(deps): update dependency qs to v6.15.2 [security]#958renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
Contributor
Author
|
7a4a53d to
feeaab3
Compare
cd52c67 to
eea659a
Compare
eea659a to
3c4d27b
Compare
3c4d27b to
a7925c7
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.12.0→6.15.2qs'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).
qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/undefined entries in comma-format arrays when encodeValuesOnly is set
CVE-2026-8723 / GHSA-q8mj-m7cp-5q26
More information
Details
Summary
qs.stringifythrowsTypeErrorwhen called witharrayFormat: 'comma'andencodeValuesOnly: trueon an array containingnullorundefined. The throw is synchronous and not handled by any of qs's null-related options (skipNulls,strictNullHandling).Details
In the comma +
encodeValuesOnlybranch,lib/stringify.js:145mapped the array through the raw encoder before joining:utils.encode(lib/utils.js:195) readsstr.lengthwith no null guard, so anullorundefinedelement throwsTypeError.skipNullsandstrictNullHandlingare both checked in the per-element loop below this line and never get a chance to run.Same class of bug as the filter-array path fixed in 0c180a4. The vulnerable shape of the comma +
encodeValuesOnlybranch was introduced in 4c4b23d ("encode comma values more consistently", PR #463, 2023-01-19), first released in v6.11.1.PoC
Fix
lib/stringify.js:145, applied in 21f80b3 onmain:nullandundefinednow pass throughmaybeMapunchanged and reach thejoin(',')step as-is. For{ a: [null, 'b'] }this producesa=,b, matching the non-encodeValuesOnlycomma path (which already joins before encoding and producesa=%2Cbfor the same input). Single-element[null]arrays still collapse via the existingobj.join(',') || nulland remain subject toskipNulls/strictNullHandlingin the main loop.Affected versions
>=6.11.1 <=6.15.1The vulnerable code shape was introduced in 4c4b23d and first shipped in v6.11.1. Earlier versions — including all of 6.7.x, 6.8.x, 6.9.x, 6.10.x, and 6.11.0 — implemented the comma +
encodeValuesOnlypath differently (joining before encoding) and are not affected. Empirically verified across released versions.Impact
Application code that calls
qs.stringifywith botharrayFormat: 'comma'andencodeValuesOnly: true(both non-default) on input that may contain anullorundefinedarray element will throw synchronously instead of producing a query string. In a typical Node.js HTTP framework (Express, Fastify, Koa, hapi) the sync throw is caught by the framework's error boundary and the affected request returns a 500; the worker process does not exit and subsequent requests are unaffected. The "kills the worker process" framing applies only to call sites outside a request-handler error boundary (background jobs, startup paths, stream pipelines) or to deployments with framework error handling explicitly disabled.The vulnerable input is a
nullorundefinedentry inside an array; this is reachable from JSON request bodies or from application code constructing arrays from user input, but not from standard HTML form submissions (which produce strings or omitted fields, not literalnull).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:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
ljharb/qs (qs)
v6.15.2Compare Source
stringify: skip null/undefined entries inarrayFormat: 'comma'+encodeValuesOnlyinstead of crashing inencoderstringify: use configureddelimiteraftercharsetSentinel(#555)stringify: applyformatterto encoded key understrictNullHandling(#554)stringify: skip null/undefined filter-array entries instead of crashing inencoder(#551)parse: handle nested bracket groups and add regression tests (#530)@ljharb/eslint-configv6.15.1Compare Source
parse:parameterLimit: InfinitywiththrowOnLimitExceeded: truesilently drops all parameters@ljharb/eslint-config@ljharb/eslint-config,iconv-litev6.15.0Compare Source
parse: addstrictMergeoption to wrap object/primitive conflicts in an array (#425, #122)duplicatesoption should not apply to bracket notation keys (#514)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
[]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+=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.