Cloudanix VulnDB

CVE-2026-82562

Low · 3.7

CVSS

3.7

EPSS

0.5%

Published

Aug 30, 2026

CISA due date

—

Cloudanix analysis

Schedule a fix SSVC: Track

A web parameter parser can ignore its own list-size limit for one kind of field name, so a large request may use more memory than expected and slow or crash the service.

Exploitation
Remote Unauthenticated
Attacker needs
None
Complexity
Moderate
Impact
Denial Of Service
Component
Library
Class
Denial of service
Remediation
Upgrade
Effort
Low
Patch risk
Low

What it actually does

The qs query-string parser, when invoked with comma splitting and hard array-limit enforcement both enabled, fails to count comma-delimited tokens against arrayLimit if the parameter uses the bracket-push key form. The value is split into a nested array and then wrapped so the post-split limit check only ever sees a single outer element, while the same payload under a flat, indexed, nested, or dotted key correctly throws RangeError. A single untrusted parameter can therefore allocate an inner array whose length tracks the number of commas, defeating the cap added after CVE-2026-2391. Memory cost remains linear in attacker-supplied bytes (on the order of microseconds and a handful of retained bytes per input byte), not a small-input amplification primitive; Node’s default HTTP header size and any body-size limit still bound total allocation. Affected qs releases are >=6.14.2 and <6.16.0; the incomplete isFlatArrayValue gate is removed in 6.16.0 so every comma-split value is counted before allocation.

Why it matters to the business

Applications that deliberately turned on a hard array-size cap can still be forced to allocate large nested arrays from one request parameter, causing heap growth, worker stalls, or process crashes and undermining an availability control operators believed was in force. Real-world blast radius is constrained: both comma parsing and throwOnLimitExceeded are non-default, so only stacks that opted into those qs options are exposed, and transport-layer request or body size limits fully contain the cost. Red Hat Grafana 12.4, 13.1, and 13.2 package streams shipped the vulnerable qs range, so Grafana services on those builds inherit the gap until RHSA-2026:68754 is applied. The issue is not in CISA KEV, is not tied to ransomware, has exploit maturity None, and is scored CVSS 3.7; about 34 days after publication there is no evidence of in-the-wild abuse. Patching is still warranted because a documented safety control fails open on one key spelling and internet-facing Grafana or other qs consumers can be probed without authentication.

How an attack unfolds

An unauthenticated client that can reach any HTTP endpoint whose query string or application/x-www-form-urlencoded body is parsed by qs 6.14.2 through 6.15.3 with comma splitting and throwOnLimitExceeded enabled submits a parameter whose name uses the bracket-push form and whose value is a long comma-separated list. The parser splits on commas, wraps the result so the outer arrayLimit check sees length 1, and retains a nested array proportional to the supplied tokens instead of throwing RangeError. Enlarging that value up to the configured request-line or body-size ceiling maximizes heap use; repeating the request against remaining workers can degrade availability. No privileges, user interaction, or secondary vulnerability are required beyond network reachability to the parser. There are no named threat actors or ransomware campaigns associated with this CVE, and no public exploit tooling is reported. Impact is an opt-in hard limit failing open, not unbounded allocation from a tiny input.

How to fix it

Upgrade the qs library to 6.16.0 or later, which counts every comma-split value against arrayLimit before splitting regardless of key form; in-limit groups under bracket-push keys still count as one outer element, and the default throwOnLimitExceeded:false path is unchanged. For Red Hat Grafana packages apply RHSA-2026:68754: grafana12-4-main to 12.4.9-0.4.hum1, grafana13-1-main to 13.1.3-0.4.hum1, and grafana13-2-main to 13.2.1-0.1.hum1, then rebuild or roll images so lockfiles no longer pin qs 6.14.2–6.15.3. If an immediate upgrade is not possible, keep strict HTTP request-line and body size limits (Node’s default 16 KB header cap already bounds query strings on the request line), and avoid enabling comma and throwOnLimitExceeded together until patched. Do not treat a bump that only addressed CVE-2026-2391 (qs 6.14.2) as sufficient for this gap.

How to confirm the fix worked

Confirm runtime and lockfile qs is 6.16.0 or newer, or that Grafana RPM/container builds match 12.4.9-0.4.hum1, 13.1.3-0.4.hum1, or 13.2.1-0.1.hum1. After upgrade, parsing a bracket-push key whose comma-separated value exceeds arrayLimit with throwOnLimitExceeded true must throw the same RangeError as a flat key; an in-limit bracket-push group should still parse as one outer element. Inventory every qs.parse / qs.parseValues call site for comma:true (and throwOnLimitExceeded:true) including transitive Grafana and other Node services. Verify reverse-proxy and Node max-header and body-size limits are enforced in staging. Regression-test that other key forms (flat, indexed, nested, dotted with allowDots) still enforce the limit and that default non-throwing behavior is unchanged.

Typical attack path

  1. Locate an HTTP endpoint that parses untrusted query strings or urlencoded bodies with qs and has both comma splitting and throwOnLimitExceeded enabled (non-default).
  2. Send a request whose parameter name uses the bracket-push key form and whose value is a comma-separated list longer than the configured arrayLimit.
  3. Confirm the parser accepts the input and allocates a nested array rather than throwing RangeError, unlike the same value under a flat or indexed key.
  4. Increase the comma-separated value up to the reverse-proxy, Node header, or body-size limit to maximize heap allocation on each request.
  5. Replay the request against additional workers or instances to induce memory pressure, event-loop delay, or process exit.

How to detect it

There is no public exploit kit or named actor TTP for this CVE, so detection of prior abuse is behavioral. Review HTTP access and error logs since publication for unusually long query strings or application/x-www-form-urlencoded bodies whose parameter names use the bracket-push form and whose values contain dense comma-separated tokens, especially where Content-Length or request-line length approaches configured maxima. Correlate those requests with Node.js heap-out-of-memory exits, Grafana or other Node worker restarts, and application logs that show RangeError on flat or indexed keys but successful parses of similar bracket-push forms. Inspect package-lock, npm ls, container SBOM, and RPM NEVRA from the incident window for qs 6.14.2–6.15.3 or unpatched grafana12-4-main / grafana13-1-main / grafana13-2-main builds. Stack traces mentioning qs lib/parse.js during request handling plus linear memory growth with request size are consistent with this parser path; absence of the documented Array-limit RangeError on bracket-push keys is expected on vulnerable builds and is not by itself proof of attack.

  • \[\]=[^&\s]*,[^&\s]*,
  • RangeError: Array limit exceeded
  • JavaScript heap out of memory
  • qs/lib/parse.js
  • "qs": "6.14.
  • "qs": "6.15.
  • node_modules/qs/package.json
  • grafana12-4-main
  • grafana13-1-main
  • grafana13-2-main
  • RHSA-2026:68754
  • application/x-www-form-urlencoded

What your security team should do

  • Patch first: upgrade qs to 6.16.0+ everywhere it is a direct or transitive dependency, and apply RHSA-2026:68754 to Grafana 12.4/13.1/13.2 streams with the exact package versions above.
  • Inventory Node services for qs.parse options that set comma and throwOnLimitExceeded together; those are the only configurations this CVE bypasses.
  • Do not assume the CVE-2026-2391 fix (qs 6.14.2) closed this path; treat 6.14.2 through 6.15.3 as still vulnerable.
  • Enforce conservative request-line and urlencoded-body size limits at the proxy and application layers so linear allocation cannot exhaust hosts even before the library patch lands.
  • Hunt access logs and Node OOM events for oversized bracket-push parameters, then confirm whether those hosts were still on qs 6.14.2–6.15.3.
  • Because this is not KEV, not ransomware-linked, and has no known exploitation, use a standard but prompt patch window unless Grafana or another qs consumer is internet-facing with the two non-default options enabled.

The record

### 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.

Affected packages

Ecosystem Package Introduced Fixed

Related vulnerabilities