Repository navigation
chore(deps): update dependency qs@<6.14.1 to >=6.16.1 [security] - #3847
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
✅ Deploy Preview for brilliant-pasca-3e80ec canceled.
|
🚀 Performance Test ResultsTest Configuration:
Test Metrics:
📜 Logs |
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
from
March 1, 2026 21:08
cb07b7a to
99b7163
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
2 times, most recently
from
March 5, 2026 09:57
e2788d9 to
c2f7e09
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
from
March 5, 2026 17:41
c2f7e09 to
04b8130
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
from
April 15, 2026 22:05
04b8130 to
550a1a3
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
2 times, most recently
from
May 9, 2026 23:48
9b1d0ec to
9c74e25
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
from
June 3, 2026 14:58
9c74e25 to
9ca9c96
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
from
October 3, 2026 23:03
9ca9c96 to
ea33f2e
Compare
renovate
Bot
force-pushed
the
renovate-npm-qs-6.14.1-vulnerability
branch
from
October 25, 2026 02:38
ea33f2e to
c76df89
Compare
This branch has not been deployed
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.14.1→>=6.16.1qs array-limit bypass via bracket-key comma parsing
CVE-2026-82562 / GHSA-x5fp-wj9c-mxmx
More information
Details
Summary
qsv6.15.3allows bracket-key input to bypassarrayLimitandthrowOnLimitExceededwhencomma: true. The inputa[]=1,2,3,4succeeds witharrayLimit: 3, while the equivalent plain-key input is rejected.Affected version tested:
Details
parseArrayValue()enforces the comma limit only for flat values. Thea[]form is marked non-flat, so its comma-separated value is wrapped after parsing and the inner array is not checked. A single parameter can therefore materialize arbitrarily large arrays.PoC
On
v6.15.3, the first input parses successfully and the second creates an array with 1,000,001 elements. The equivalenta=1,2,3,4input throwsRangeErroras expected.Impact
An attacker who can supply a query string or form body can bypass configured array limits and force excessive memory allocation, causing denial of service. The limit must be applied after comma splitting and before the resulting array is wrapped.
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).
qs: Denial of Service via Attacker Controlled isBuffer
CVE-2026-82417 / GHSA-4mjr-xmp4-gh2g
More information
Details
Summary
qs.stringify()callsutils.isBuffer()on every value it serializes, andutils.isBuffer()invokesobj.constructor.isBuffer(obj)without checking that it is callable. A value whose ownconstructor.isBufferis a non-function makesqscall a non-callable and throwTypeError. Such a value is produced byqs.parseitself from an untrusted query string whenplainObjects: trueorallowPrototypes: trueis set, so a pure-qsparse→stringifyround-trip — noJSON.parse— turns an unauthenticated query string into an uncaught throw.An attacker-controlled
parseinput reaches the host application's availability asset — viaqs's own recommendedplainObjectsmitigation — and triggers an uncaught exception during aparse→stringifyround-trip.Details
utils.isBufferruns atlib/stringify.js:127for every serialized value:utils.isBuffer(lib/utils.js:327-333) invokesobj.constructor.isBufferwithout verifying it is callable:constructorandisBufferare ordinary keys.qs.parsewithplainObjects: trueorallowPrototypes: truekeeps them as own properties, so the parsed value carries a non-functionconstructor.isBuffer;stringifythen calls a non-callable and throwsTypeError. By contrastutils.isRegExpuses a brand check (Object.prototype.toString); the missing guard here is an internal inconsistency, not a platform limitation.Trust Boundary Note
qs.stringifyalone treats its input as caller-constructed, so serializing a hostile object could be argued outside its contract. This report does not depend on that framing: the malicious shape is produced byqs.parse, whose input is untrusted by design.qs.parsenormally strips aconstructorkey via its prototype guard, but with the documented optionsplainObjects: trueorallowPrototypes: truethe key survives and lands as an own property. Feeding the parsed object back intoqs.stringify— the standard round-trip in gateways and request-forwarders — then hits the unchecked call.PoC
poc02c_isBuffer_qs_only_roundtrip.js— pure-qschain, noJSON.parse; an untrusted query string alone reaches the throw:poc02_isBuffer.js— the minimal defect:poc02b_isBuffer_async_crash.js— worker death in an async sink:Execution Steps
Reproduction Evidence
poc02c_isBuffer_qs_only_roundtrip.js:poc02_isBuffer.js:poc02b_isBuffer_async_crash.js:The pure-
qsround-trip shows the malicious shape originates fromqs.parseof an untrusted query string, with noJSON.parse. The synchronoustry/catchin the async case does not catch the throw; the process exits with code 1, denying service to all requests on that worker.Impact
An unauthenticated request degrades any endpoint that re-serializes deserialized client data with
qs.stringify. The primary impact is a per-request failure: the handler throws and the framework returns HTTP 500. Where the call sits in an unguarded async continuation, the throw escapes and the worker process exits, denying service to all requests it was handling, which means a higher impact that depends on the application's error handling, not onqs.Recommended Fix
Replace the duck-type with a brand check mirroring
utils.isRegExp:If duck-typing must remain, require
typeof obj.constructor.isBuffer === 'function'before invoking and wrap the call intry/catch.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@<6.14.1)
v6.16.1Compare Source
parse: do not mutate an object inputstringify: stop re-encoding structural separator dots whenencodeDotInKeysis set (#564)stringify:arrayFormat: 'comma': pass the full encoder arguments withencodeValuesOnlyutils: encode+as%2Bin iso-8859-1 mode so values round-trip (#565)stringify: ignore inherited array format names (#622)stringify:arrayFormat: 'comma': do not throw on elements with no callabletoStringutils:merge: seed an overflow container's index from its own keys, not just the sourceutils:merge: keep astrictMergeconflict container's index andarrayLimitcorrectparse: only treat[]as array syntax when it ends the keydecode: skip decoders when there is no percent sign (#583)utils:merge: applyarrayLimitto the two-element array built for colliding valuesparse: bound the nesting added by repeatedstrictMergeconflicts (credit @Yeaseen)qsand flat parsers disagree about parameter namesthrowOnLimitExceededlimits each array, not the total number of valuescache-modeutils:decode: add missing casesparse: characterize the]=split when an=precedes any bracket group (#620)parse:allowDots: cover stray close brackets before a dot@ljharb/eslint-config,eslint,tapev6.16.0Compare Source
stringify: add adepthoption to bound recursion depth (defaultInfinity)parse: enforcearrayLimiton comma groups under[]=whenthrowOnLimitExceededis setparse: flatten a collection appended to an overflowed array (#571)utils:isBuffer: do not invoke a non-callableconstructor.isBufferstringify: do not letallowEmptyArraysskip cycle detection (or drop own keys) on an empty array with own propertiesstringify: encode dots in a top-level key with a primitive value when encodeDotInKeys is set (#562)stringifydeep-nesting DoS is caller-boundedarrayLimitis a representation threshold, not an element-count capparse: remove a test that pinned[]=comma groups escapingarrayLimitstringify: pin currentencodeDotInKeysseparator-dot behavior@ljharb/eslint-config,eslinteslint,evalmdv6.15.3Compare Source
parse: enforcethrowOnLimitExceededfor cumulative array growth viacombine/mergeutils: respect encoding of surrogate pairs across chunks (#559)parse: throw thearrayLimiterror before splitting oversized comma valuesutils.merge/utils.assign: avoid invoking__proto__setter when copying own propertiesutils: enforcearrayLimitconsistently acrossmerge's array pathsutils: makecompactO(n) via a side-channel visited-set instead ofArray.indexOfside-channeleslint,mock-property,tapeparse: characterize current lenient handling of unbalanced bracket keys (#558)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); changes output for some unbalanced bracket keys (see #558)@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)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.