CVE-2026-82562
qs.parse does not enforce arrayLimit on comma groups under bracket-push keys when throwOnLimitExceeded is set (incomplete fix for CVE-2026-2391)
Summary
When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover.
Details
In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained.
PoC
var qs = require('qs');
var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true };
qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array.
qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw)
qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true });
// no throw; a 1,000,001-element inner array is allocated
Fix
lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged.
Affected versions
>=6.14.2 <6.16.0, fixed in v6.16.0.
v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option.
Impact
An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
6.3
qs.parse does not enforce arrayLimit on comma groups under bracket-push keys when throwOnLimitExceeded is set (incomplete fix for CVE-2026-2391)
Summary
When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover.
Details
In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained.
PoC
var qs = require('qs');
var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true };
qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array.
qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw)
qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true });
// no throw; a 1,000,001-element inner array is allocated
Fix
lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged.
Affected versions
>=6.14.2 <6.16.0, fixed in v6.16.0.
v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option.
Impact
An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
- Record
CVE-2026-82562- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 3.7 Low
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
EUVDEUVD-2026-68141
6.3
Summary
When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover.
Details
In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained.
PoC
var qs = require('qs');
var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true };
qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array.
qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw)
qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true });
// no throw; a 1,000,001-element inner array is allocated
Fix
lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged.
Affected versions
>=6.14.2 <6.16.0, fixed in v6.16.0.
v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option.
Impact
An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
- Record
EUVD-2026-68141- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-x5fp-wj9c-mxmx
6.3
qs array-limit bypass via bracket-key comma parsing
Summary
qs v6.15.3 allows bracket-key input to bypass arrayLimit and throwOnLimitExceeded when comma: true. The input a[]=1,2,3,4 succeeds with arrayLimit: 3, while the equivalent plain-key input is rejected.
Affected version tested:
qs v6.15.3
commit 18d085e919dae70c8f1b200ab99323058edab2c2
Details
parseArrayValue() enforces the comma limit only for flat values. The a[] 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
const qs = require('qs')
const options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }
const result = qs.parse('a[]=1,2,3,4', options)
console.log(result.a[0].length) // 4; expected RangeError
const big = qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20 })
console.log(big.a[0].length) // 1000001
On v6.15.3, the first input parses successfully and the second creates an array with 1,000,001 elements. The equivalent a=1,2,3,4 input throws RangeError as 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.
- Record
GHSA-x5fp-wj9c-mxmx- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 3.7 Low
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
NVD
6.3
Summary
When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover.
Details
In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained.
PoC
var qs = require('qs');
var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true };
qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array.
qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw)
qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true });
// no throw; a 1,000,001-element inner array is allocated
Fix
lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged.
Affected versions
>=6.14.2 <6.16.0, fixed in v6.16.0.
v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option.
Impact
An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
- Record
CVE-2026-82562- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 3.7 Low
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
OSV
6.3
qs.parse does not enforce arrayLimit on comma groups under bracket-push keys when throwOnLimitExceeded is set (incomplete fix for CVE-2026-2391)
Summary
When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover.
Details
In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained.
PoC
var qs = require('qs');
var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true };
qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array.
qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw)
qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true });
// no throw; a 1,000,001-element inner array is allocated
Fix
lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged.
Affected versions
>=6.14.2 <6.16.0, fixed in v6.16.0.
v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option.
Impact
An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
- Record
CVE-2026-82562- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-82562
6.3
Summary When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover. ### Details In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained. #### PoC js var qs = require('qs'); var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }; qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array. qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw) qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true }); // no throw; a 1,000,001-element inner array is allocated #### Fix lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged. ### Affected versions >=6.14.2 <6.16.0, fixed in v6.16.0. v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option. ### Impact An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
- Record
DEBIAN-CVE-2026-82562- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
Show 13 moreShow less
OSVGHSA-x5fp-wj9c-mxmx
6.3
qs array-limit bypass via bracket-key comma parsing
Summary
qs v6.15.3 allows bracket-key input to bypass arrayLimit and throwOnLimitExceeded when comma: true. The input a[]=1,2,3,4 succeeds with arrayLimit: 3, while the equivalent plain-key input is rejected.
Affected version tested:
qs v6.15.3
commit 18d085e919dae70c8f1b200ab99323058edab2c2
Details
parseArrayValue() enforces the comma limit only for flat values. The a[] 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
const qs = require('qs')
const options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }
const result = qs.parse('a[]=1,2,3,4', options)
console.log(result.a[0].length) // 4; expected RangeError
const big = qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20 })
console.log(big.a[0].length) // 1000001
On v6.15.3, the first input parses successfully and the second creates an array with 1,000,001 elements. The equivalent a=1,2,3,4 input throws RangeError as 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.
- Record
GHSA-x5fp-wj9c-mxmx- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 3.7 Low
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVRHSA-2026:60866
9.1
Red Hat Security Advisory: Red Hat Hardened Images RPMs Security Update
- Record
RHSA-2026:60866- CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
OSVRHSA-2026:62544
7.5
Red Hat Security Advisory: Red Hat Hardened Images RPMs Security Update
- Record
RHSA-2026:62544- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-02
OSVRHSA-2026:63164
8.8
Red Hat Security Advisory: Red Hat Hardened Images RPMs bug fix and enhancement update
- Record
RHSA-2026:63164- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-82562
6.3
Summary When qs.parse is called with comma: true and throwOnLimitExceeded: true, a comma-separated value under a bracket-push key (a[]=1,2,3,4) is split into an array without being compared against arrayLimit, while the same value under a flat key (a=1,2,3,4), an indexed key (a[0]=), a nested key (a[b]=), or a dotted key (a.b= with allowDots) throws the documented RangeError. A single parameter such as a[]=1,2,2,... therefore produces an inner array of arbitrary length even though the caller opted into the hard limit. This is the []= key form that the fix for CVE-2026-2391 (qs 6.14.2) did not cover. ### Details In lib/parse.js, a comma-separated value under a []= key is split and then wrapped as a single nested element (val = [val], so that each a[]=x,y group counts as one element of the outer array). The arrayLimit check that 6.14.2 added for comma values runs after that wrap, so for []= parts it only ever saw the wrapper of length 1. 6.15.3 added a pre-split comma count so that an oversized value throws before it is allocated, but gated it on an isFlatArrayValue flag that parseValues set to false for any part containing []=, and did not pass it for object-valued input, so the gap remained. #### PoC js var qs = require('qs'); var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }; qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array. qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (no throw) qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true }); // no throw; a 1,000,001-element inner array is allocated #### Fix lib/parse.js, applied in 8859c37 on main and released as v6.16.0: the isFlatArrayValue gate is removed, so every comma-split value is counted against arrayLimit before splitting regardless of key form. An in-limit group under a[]= still counts as one element of the outer array, and the default (throwOnLimitExceeded: false) path is unchanged. ### Affected versions >=6.14.2 <6.16.0, fixed in v6.16.0. v6.14.2 introduced arrayLimit enforcement for comma values (the fix for CVE-2026-2391) but only for values not under a []= key, and every release from v6.14.2 through v6.15.3 has the same gap. v6.14.0 and v6.14.1, where throwOnLimitExceeded exists but does not apply to any comma form, are covered by CVE-2026-2391 rather than this record. Earlier lines (6.7.x through 6.13.x) have comma but no throwOnLimitExceeded, so there is no hard cap on any comma path to bypass; releases before 6.7.0 have no comma option. ### Impact An unauthenticated attacker who can reach an application that parses untrusted query strings or urlencoded bodies with both comma: true and throwOnLimitExceeded: true (both non-default) can bypass the configured limit with a single a[]= parameter and force the parser to allocate an array proportional to the request size. The cost is strictly linear in the attacker-supplied bytes (about 0.1 microseconds and 6 to 7 retained bytes per input byte; the same out-of-memory threshold as the documented default throwOnLimitExceeded: false path), so a transport-layer request or body size limit bounds it completely (and node's default maximum HTTP header size of 16 KB already bounds the request line, so multi-megabyte payloads need a body parser). The impact is that an opt-in hard limit fails open on one key spelling, not unbounded allocation from a small input.
- Record
UBUNTU-CVE-2026-82562- CVSS 4.0
- 6.3 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N - CVSS 3.1
- 3.7 Low
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
OSVCLSA-2026-1790541933 No score
TuxCare security update for qs (2 CVEs)
TuxCare rebuilt qs to address 2 CVEs. Fixed in 6.15.3-tuxcare.1.
- Record
CLSA-2026-1790541933- Updated
- 2026-11-02
OSVCLSA-2026-1791453817 No score
TuxCare security update for qs (1 CVE)
TuxCare rebuilt qs to address 1 CVE. Fixed in 6.10.7-tuxcare.3.
- Record
CLSA-2026-1791453817- Updated
- 2026-11-02
OSVCLSA-2026-1791626353 No score
TuxCare security update for qs (1 CVE)
TuxCare rebuilt qs to address 1 CVE. Fixed in 6.10.3-tuxcare.3.
- Record
CLSA-2026-1791626353- Updated
- 2026-11-02
OSVCLSA-2026-1792449761 No score
TuxCare security update for qs (3 CVEs)
TuxCare rebuilt qs to address 3 CVEs. Fixed in 6.14.2-tuxcare.1.
- Record
CLSA-2026-1792449761- Updated
- 2026-11-02
OSVCLSA-2026-1793015982 No score
TuxCare security update for qs (1 CVE)
TuxCare rebuilt qs to address 1 CVE. Fixed in 6.13.0-tuxcare.4.
- Record
CLSA-2026-1793015982- Updated
- 2026-11-02
OSVCLSA-2026-1793098692 No score
TuxCare security update for qs (1 CVE)
TuxCare rebuilt qs to address 1 CVE. Fixed in 6.14.0-tuxcare.4.
- Record
CLSA-2026-1793098692- Updated
- 2026-11-02
OSVCLSA-2026-1793718727 No score
TuxCare security update for qs (1 CVE)
TuxCare rebuilt qs to address 1 CVE. Fixed in 6.10.4-tuxcare.4.
- Record
CLSA-2026-1793718727- Updated
- 2026-11-03
OSVCLSA-2026-1793718812 No score
TuxCare security update for qs (1 CVE)
TuxCare rebuilt qs to address 1 CVE. Fixed in 6.11.2-tuxcare.4.
- Record
CLSA-2026-1793718812- Updated
- 2026-11-03
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
qsnpm |
6.14.2 to 6.15.3 | 6.16.0 |
qsTuxCare:npm From an advisory covering 2 CVEs |
6.15.3-tuxcare.0 up to 6.15.3-tuxcare.1, plus listed versions 6.15.3 |
6.15.3-tuxcare.1 |
qsTuxCare:npm |
6.10.7-tuxcare.0 up to 6.10.7-tuxcare.3, plus listed versions 6.10.76.10.7-tuxcare.16.10.7-tuxcare.2 |
6.10.7-tuxcare.3 |
qsTuxCare:npm |
6.10.3-tuxcare.0 up to 6.10.3-tuxcare.3, plus listed versions 6.10.36.10.3-tuxcare.16.10.3-tuxcare.2 |
6.10.3-tuxcare.3 |
qsTuxCare:npm From an advisory covering 3 CVEs |
6.14.2-tuxcare.0 up to 6.14.2-tuxcare.1, plus listed versions 6.14.2 |
6.14.2-tuxcare.1 |
qsTuxCare:npm |
6.13.0-tuxcare.0 up to 6.13.0-tuxcare.4, plus listed versions 6.13.06.13.0-tuxcare.16.13.0-tuxcare.26.13.0-tuxcare.3 |
6.13.0-tuxcare.4 |
qsTuxCare:npm |
6.14.0-tuxcare.0 up to 6.14.0-tuxcare.4, plus listed versions 6.14.06.14.0-tuxcare.16.14.0-tuxcare.26.14.0-tuxcare.3 |
6.14.0-tuxcare.4 |
qsTuxCare:npm |
6.10.4-tuxcare.0 up to 6.10.4-tuxcare.4, plus listed versions 6.10.46.10.4-tuxcare.16.10.4-tuxcare.26.10.4-tuxcare.3 |
6.10.4-tuxcare.4 |
qsTuxCare:npm |
6.11.2-tuxcare.0 up to 6.11.2-tuxcare.4, plus listed versions 6.11.26.11.2-tuxcare.16.11.2-tuxcare.26.11.2-tuxcare.3 |
6.11.2-tuxcare.4 |
node-qsDebian:12 |
All versions, plus listed versions 6.11.0+ds+~6.9.7-36.11.0+ds+~6.9.7-46.13.0+ds+~6.9.16-16.14.1+ds+~6.14.0-16.15.0+ds+~6.15.0-1 Show 4 moreShow less6.15.0+ds+~6.15.0-26.15.0+ds+~6.15.0-36.15.2+ds+~6.15.1-16.16.0+ds+~6.15.1-1 |
None known |
Show 14 moreShow less
| Package | Affected | Fixed |
|---|---|---|
node-qsDebian:13 |
All versions, plus listed versions 6.13.0+ds+~6.9.16-16.14.1+ds+~6.14.0-16.15.0+ds+~6.15.0-16.15.0+ds+~6.15.0-26.15.0+ds+~6.15.0-36.15.2+ds+~6.15.1-16.16.0+ds+~6.15.1-1 |
None known |
node-qsDebian:14 |
before 6.16.0+ds+~6.15.1-1, plus listed versions 6.13.0+ds+~6.9.16-16.14.1+ds+~6.14.0-16.15.0+ds+~6.15.0-16.15.0+ds+~6.15.0-26.15.0+ds+~6.15.0-36.15.2+ds+~6.15.1-1 |
6.16.0+ds+~6.15.1-1 |
qsnpm |
6.14.2 up to 6.16.0 | 6.16.0 |
grafana12.4Red Hat:hummingbird:1 From an advisory covering 6 CVEs |
before 0:12.4.9-0.4.hum1 | 0:12.4.9-0.4.hum1 |
grafana13.1Red Hat:hummingbird:1 From an advisory covering 2 CVEs |
before 0:13.1.3-0.4.hum1 | 0:13.1.3-0.4.hum1 |
grafana13.2Red Hat:hummingbird:1 From an advisory covering 10 CVEs |
before 0:13.2.1-0.1.hum1 | 0:13.2.1-0.1.hum1 |
node-qsUbuntu:Pro:14.04:LTS |
All versions, plus listed versions 0.4.2-10.6.5-10.6.5-1ubuntu0.1~esm1 |
None known |
node-qsUbuntu:16.04:LTS |
All versions, plus listed versions 2.2.4-1 |
None known |
node-qsUbuntu:18.04:LTS |
All versions, plus listed versions 2.2.4-12.2.4-1ubuntu1 |
None known |
node-qsUbuntu:Pro:20.04:LTS |
All versions, plus listed versions 6.5.2-16.9.0+ds-16.9.1+ds-16.9.1+ds-1ubuntu0.1~esm1 |
None known |
node-qsUbuntu:22.04:LTS |
All versions, plus listed versions 6.9.4+ds-16.10.1+ds-16.10.2+ds+~6.9.7-16.10.3+ds+~6.9.7-1 |
None known |
node-qsUbuntu:24.04:LTS |
All versions, plus listed versions 6.11.0+ds+~6.9.7-36.11.0+ds+~6.9.7-4 |
None known |
node-qsUbuntu:26.10 |
All versions, plus listed versions 6.14.1+ds+~6.14.0-16.15.2+ds+~6.15.1-1 |
None known |
node-qsUbuntu:26.04:LTS |
All versions, plus listed versions 6.13.0+ds+~6.9.16-16.14.1+ds+~6.14.0-1 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | ||
| affected, aliases, facts | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-82562 is a medium vulnerability (CVSS 6.3) in Ljharb Qs, published August 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.54%, the 45th percentile. Fixed in qs 6.16.0.
References
github.com/ljharb/qs/security/advisories/GHSA-x5fp-wj9c-mxmx
github.com/ljharb/qs/commit/8859c37470e11b42b547b275e4e9bd0bc8cc5464
github.com/ljharb/qs/security/advisories/GHSA-w7fw-mjwx-w883
nvd.nist.gov/vuln/detail/CVE-2026-82562
github.com/advisories/GHSA-x5fp-wj9c-mxmx
npmjs.com/qs
Show 95 moreShow less
github.com/CVEProject/cvelistV5/tree/main/cves/2026/82xxx/CVE-2026-82562.json
github.com/ljharb/qs
security-tracker.debian.org/tracker/CVE-2026-82562
access.redhat.com/errata/RHSA-2026:60866
access.redhat.com/security/cve/CVE-2026-73501
access.redhat.com/security/cve/CVE-2026-75899
access.redhat.com/security/cve/CVE-2026-75931
access.redhat.com/security/cve/CVE-2026-75975
access.redhat.com/security/cve/CVE-2026-76172
access.redhat.com/security/updates/classification
images.redhat.com
access.redhat.com/security/cve/CVE-2026-82562
security.access.redhat.com/data/csaf/v2/advisories/2026/rhsa-2026_60866.json
bugzilla.redhat.com/show_bug.cgi?id=2515006
cve.org/CVERecord?id=CVE-2026-73501
nvd.nist.gov/vuln/detail/CVE-2026-73501
github.com/getkin/kin-openapi/commit/f0407d53b0730280266f454b755010e7eeb985da
github.com/getkin/kin-openapi/releases/tag/v0.144.0
github.com/getkin/kin-openapi/security/advisories/GHSA-r277-6w6q-xmqw
bugzilla.redhat.com/show_bug.cgi?id=2521778
cve.org/CVERecord?id=CVE-2026-75899
nvd.nist.gov/vuln/detail/CVE-2026-75899
cna.openjsf.org/security-advisories.html
github.com/fastify/fast-uri/security/advisories/GHSA-fph4-wmhf-6fwf
bugzilla.redhat.com/show_bug.cgi?id=2521777
cve.org/CVERecord?id=CVE-2026-75931
nvd.nist.gov/vuln/detail/CVE-2026-75931
github.com/fastify/fast-uri/security/advisories/GHSA-5jgf-p345-68v8
bugzilla.redhat.com/show_bug.cgi?id=2521779
cve.org/CVERecord?id=CVE-2026-75975
nvd.nist.gov/vuln/detail/CVE-2026-75975
github.com/fastify/fast-uri/security/advisories/GHSA-f65p-4m7j-42xc
bugzilla.redhat.com/show_bug.cgi?id=2521798
cve.org/CVERecord?id=CVE-2026-76172
nvd.nist.gov/vuln/detail/CVE-2026-76172
github.com/fastify/fast-uri/security/advisories/GHSA-jqff-g426-hqxp
bugzilla.redhat.com/show_bug.cgi?id=2525939
cve.org/CVERecord?id=CVE-2026-82562
access.redhat.com/errata/RHSA-2026:62544
access.redhat.com/security/cve/CVE-2026-82417
security.access.redhat.com/data/csaf/v2/advisories/2026/rhsa-2026_62544.json
bugzilla.redhat.com/show_bug.cgi?id=2525936
cve.org/CVERecord?id=CVE-2026-82417
nvd.nist.gov/vuln/detail/CVE-2026-82417
github.com/ljharb/qs/commit/e83d321ffafb38cf210683ac31714fce6ce1c6c6
github.com/ljharb/qs/security/advisories/GHSA-4mjr-xmp4-gh2g
access.redhat.com/errata/RHSA-2026:63164
access.redhat.com/security/cve/CVE-2026-17033
access.redhat.com/security/cve/CVE-2026-19197
access.redhat.com/security/cve/CVE-2026-21723
access.redhat.com/security/cve/CVE-2026-9765
access.redhat.com/security/cve/CVE-2026-8595
access.redhat.com/security/cve/CVE-2026-33382
access.redhat.com/security/cve/CVE-2026-8609
access.redhat.com/security/cve/CVE-2026-84375
security.access.redhat.com/data/csaf/v2/advisories/2026/rhsa-2026_63164.json
bugzilla.redhat.com/show_bug.cgi?id=2499051
cve.org/CVERecord?id=CVE-2026-8595
nvd.nist.gov/vuln/detail/CVE-2026-8595
grafana.com/security/security-advisories/cve-2026-8595
bugzilla.redhat.com/show_bug.cgi?id=2499061
cve.org/CVERecord?id=CVE-2026-8609
nvd.nist.gov/vuln/detail/CVE-2026-8609
grafana.com/security/security-advisories/cve-2026-8609
bugzilla.redhat.com/show_bug.cgi?id=2506730
cve.org/CVERecord?id=CVE-2026-9765
nvd.nist.gov/vuln/detail/CVE-2026-9765
grafana.com/security/security-advisories/cve-2026-9765
bugzilla.redhat.com/show_bug.cgi?id=2521910
cve.org/CVERecord?id=CVE-2026-17033
nvd.nist.gov/vuln/detail/CVE-2026-17033
grafana.com/security/security-advisories/cve-2026-17033
bugzilla.redhat.com/show_bug.cgi?id=2524303
cve.org/CVERecord?id=CVE-2026-19197
nvd.nist.gov/vuln/detail/CVE-2026-19197
grafana.com/security/security-advisories/cve-2026-19197
bugzilla.redhat.com/show_bug.cgi?id=2506342
cve.org/CVERecord?id=CVE-2026-21723
nvd.nist.gov/vuln/detail/CVE-2026-21723
grafana.com/security/security-advisories/cve-2026-21723
bugzilla.redhat.com/show_bug.cgi?id=2499062
cve.org/CVERecord?id=CVE-2026-33382
nvd.nist.gov/vuln/detail/CVE-2026-33382
grafana.com/security/security-advisories/cve-2026-33382
bugzilla.redhat.com/show_bug.cgi?id=2527118
cve.org/CVERecord?id=CVE-2026-84375
nvd.nist.gov/vuln/detail/CVE-2026-84375
github.com/nodeca/js-yaml/commit/3485bc06ff8a0251505f44a00414d90df2466639
github.com/nodeca/js-yaml/commit/6a8e05f9a485188ed730ac81e81ae221352ef480
github.com/nodeca/js-yaml/commit/d90b6612a5a84385bdcb556c44578eac76dc0f6b
github.com/nodeca/js-yaml/pull/797
github.com/nodeca/js-yaml/releases/tag/3.15.2
github.com/nodeca/js-yaml/releases/tag/4.3.2
github.com/nodeca/js-yaml/security/advisories/GHSA-2883-xcg3-v3hh
ubuntu.com/security/CVE-2026-82562