Description
### Summary
The `arrayLimit` option in qs does not enforce limits for comma-separated values when `comma: true` is 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 `comma` option is set to `true` (not the default, but configurable in applications), qs allows parsing comma-separated strings as arrays (e.g., `?param=a,b,c` becomes `['a', 'b', 'c']`). However, the limit check for `arrayLimit` (default: 20) and the optional throwOnLimitExceeded occur after the comma-handling logic in `parseArrayValue`, 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):
```js
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
    return val.split(',');
}

if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {
    throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
}

return val;
```
The `split(',')` returns the array immediately, skipping the subsequent limit check. Downstream merging via `utils.combine` does 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 of `arrayLimit`, 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:**
```
npm install qs
```

```js
const qs = require('qs');

const payload = 'a=' + ','.repeat(25); // 26 elements after split (bypasses arrayLimit: 5)
const options = { comma: true, arrayLimit: 5, throwOnLimitExceeded: true };

try {
  const result = qs.parse(payload, options);
  console.log(result.a.length); // Outputs: 26 (bypass successful)
} catch (e) {
  console.log('Limit enforced:', e.message); // Not thrown
}
```
**Configuration:**
- `comma: true`
- `arrayLimit: 5`
- `throwOnLimitExceeded: true`

Expected: Throws "Array limit exceeded" error.
Actual: Parses successfully, creating an array of length 26.


### Impact
Denial of Service (DoS) via memory exhaustion.
Published: 2026-02-12
Score: 6.3 Medium
EPSS: < 1% Very Low
KEV: No
Impact: Denial of Service (DoS) via memory exhaustion
Action: Patch
AI Analysis

Impact

The qs library’s arrayLimit enforcement is bypassed when the comma option is enabled, allowing an attacker to craft a single query parameter that contains millions of commas. This results in an unbounded array allocation that consumes vast amounts of memory and can crash or hang the Node.js process. The flaw is a CWE-179 (Input Validation Error) and CWE-20 (Improper Input Validation) weakness, exposing the application to denial‑of‑service without requiring any privileged access.

Affected Systems

Any Node.js application that includes the qs package prior to the fix in v6.14.1 and configures the `comma: true` option is affected. The vulnerability also applies to older releases that lack the patch and rely on the default arrayLimit setting.

Risk and Exploitability

The CVSS score of 6.3 indicates a moderate severity. The EPSS score of less than 1% suggests that exploitation is presently unlikely in the wild, and the vulnerability is not listed in the CISA KEV catalog. However, if an application accepts high‑volume traffic or is under attack, the bypass can be leveraged to exhaust server resources. The attack requires only that the target accept HTTP requests containing a comma‑delimited payload, making it a low‑barrier vector for DoS.

Generated by OpenCVE AI on April 18, 2026 at 12:36 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Upgrade the qs library to version 6.14.1 or later, where the comma handling is correctly limited.
  • If an upgrade cannot be applied immediately, set `arrayLimit` to the strictest value required, enable `throwOnLimitExceeded: true`, and avoid enabling `comma: true` unless absolutely necessary.
  • Avoid enabling the `comma` option in production environments that do not require it.
  • Implement upstream request filtering to reject or truncate query strings containing excessively long lists of comma‑separated values.

Generated by OpenCVE AI on April 18, 2026 at 12:36 UTC.

Tracking

Sign in to view the affected projects.

Advisories
Source ID Title
Github GHSA Github GHSA GHSA-w7fw-mjwx-w883 qs's arrayLimit bypass in comma parsing allows denial of service
History

Tue, 24 Feb 2026 20:15:00 +0000

Type Values Removed Values Added
First Time appeared Qs Project
Qs Project qs
Weaknesses NVD-CWE-noinfo
CPEs cpe:2.3:a:qs_project:qs:*:*:*:*:*:node.js:*:*
Vendors & Products Qs Project
Qs Project qs

Fri, 13 Feb 2026 00:15:00 +0000

Type Values Removed Values Added
Weaknesses CWE-179
References
Metrics threat_severity

None

threat_severity

Moderate


Thu, 12 Feb 2026 15:15:00 +0000

Type Values Removed Values Added
Metrics ssvc

{'options': {'Automatable': 'yes', 'Exploitation': 'poc', 'Technical Impact': 'partial'}, 'version': '2.0.3'}


Thu, 12 Feb 2026 10:15:00 +0000

Type Values Removed Values Added
First Time appeared Ljharb
Ljharb qs
Vendors & Products Ljharb
Ljharb qs

Thu, 12 Feb 2026 05:15:00 +0000

Type Values Removed Values Added
Description ### Summary The `arrayLimit` option in qs does not enforce limits for comma-separated values when `comma: true` is 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 `comma` option is set to `true` (not the default, but configurable in applications), qs allows parsing comma-separated strings as arrays (e.g., `?param=a,b,c` becomes `['a', 'b', 'c']`). However, the limit check for `arrayLimit` (default: 20) and the optional throwOnLimitExceeded occur after the comma-handling logic in `parseArrayValue`, 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): ```js if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {     return val.split(','); } if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {     throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.'); } return val; ``` The `split(',')` returns the array immediately, skipping the subsequent limit check. Downstream merging via `utils.combine` does 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 of `arrayLimit`, 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:** ``` npm install qs ``` ```js const qs = require('qs'); const payload = 'a=' + ','.repeat(25); // 26 elements after split (bypasses arrayLimit: 5) const options = { comma: true, arrayLimit: 5, throwOnLimitExceeded: true }; try {   const result = qs.parse(payload, options);   console.log(result.a.length); // Outputs: 26 (bypass successful) } catch (e) {   console.log('Limit enforced:', e.message); // Not thrown } ``` **Configuration:** - `comma: true` - `arrayLimit: 5` - `throwOnLimitExceeded: true` Expected: Throws "Array limit exceeded" error. Actual: Parses successfully, creating an array of length 26. ### Impact Denial of Service (DoS) via memory exhaustion.
Title qs's arrayLimit bypass in comma parsing allows denial of service
Weaknesses CWE-20
References
Metrics cvssV3_1

{'score': 3.7, 'vector': 'CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L'}

cvssV4_0

{'score': 6.3, 'vector': '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'}


cve-icon MITRE

Status: PUBLISHED

Assigner: harborist

Published:

Updated: 2026-02-12T17:32:05.953Z

Reserved: 2026-02-12T03:52:09.332Z

Link: CVE-2026-2391

cve-icon Vulnrichment

Updated: 2026-02-12T15:00:12.364Z

cve-icon NVD

Status : Analyzed

Published: 2026-02-12T05:17:11.187

Modified: 2026-02-24T20:13:51.837

Link: CVE-2026-2391

cve-icon Redhat

Severity : Moderate

Publid Date: 2026-02-12T04:39:42Z

Links: CVE-2026-2391 - Bugzilla

cve-icon OpenCVE Enrichment

Updated: 2026-04-18T12:45:45Z