{"schema_version":"1.7.3","id":"GHSA-6rw7-vpxm-498p","published":"2025-12-30T21:02:54Z","modified":"2026-03-04T15:06:33.112273Z","aliases":["CVE-2025-15284"],"related":["CGA-x345-fh92-pxw2"],"summary":"qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion","details":"### Summary\n\nThe `arrayLimit` option 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; `arrayLimit` should apply uniformly across all array notations.\n\n**Note:** The default `parameterLimit` of 1000 effectively mitigates the DoS scenario originally described. With default options, bracket notation cannot produce arrays larger than `parameterLimit` regardless of `arrayLimit`, because each `a[]=value` consumes one parameter slot. The severity has been reduced accordingly.\n\n### Details\n\nThe `arrayLimit` option only checked limits for indexed notation (`a[0]=1&a[1]=2`) but did not enforce it for bracket notation (`a[]=1&a[]=2`).\n\n**Vulnerable code** (`lib/parse.js:159-162`):\n```javascript\nif (root === '[]' && options.parseArrays) {\n    obj = utils.combine([], leaf);  // No arrayLimit check\n}\n```\n\n**Working code** (`lib/parse.js:175`):\n```javascript\nelse if (index <= options.arrayLimit) {  // Limit checked here\n    obj = [];\n    obj[index] = leaf;\n}\n```\n\nThe 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.\n\n### PoC\n\n```javascript\nconst qs = require('qs');\nconst result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 });\nconsole.log(result.a.length);  // Output: 6 (should be max 5)\n```\n\n**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.\n\n### Impact\n\nConsistency bug in `arrayLimit` enforcement. With default `parameterLimit`, the practical DoS risk is negligible since `parameterLimit` already caps the total number of parsed parameters (and thus array elements from bracket notation). The risk increases only when `parameterLimit` is explicitly set to a very high value.","affected":[{"package":{"name":"qs","ecosystem":"npm","purl":"pkg:npm/qs"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"6.14.1"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/12/GHSA-6rw7-vpxm-498p/GHSA-6rw7-vpxm-498p.json"}}],"references":[{"type":"WEB","url":"https://github.com/ljharb/qs/security/advisories/GHSA-6rw7-vpxm-498p"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-15284"},{"type":"WEB","url":"https://github.com/ljharb/qs/commit/3086902ecf7f088d0d1803887643ac6c03d415b9"},{"type":"PACKAGE","url":"https://github.com/ljharb/qs"}],"database_specific":{"cwe_ids":["CWE-20"],"github_reviewed":true,"github_reviewed_at":"2025-12-30T21:02:54Z","nvd_published_at":"2025-12-29T23:15:42Z","severity":"MODERATE"},"severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L"},{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L"}]}