qs CVE-2026-8723
MEDIUMAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
ReconSend JSON request with null array element
-
DeliveryApplication deserializes to object with null in array
-
ExploitCode calls qs.stringify with comma+encodeValuesOnly
-
InstallEncoder accesses null.length property
-
C2Synchronous TypeError thrown
-
ExecuteFramework error boundary catches exception
-
ImpactHTTP 500 returned to attacker
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A10:2025 - Mishandling of Exceptional Conditions
ASVS 5.0
V16 - Security Logging and Error Handling Null pointer safety, defensive checks
MITRE ATT&CK
1 technique across 1 tactic: Impact The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires the target application to call qs.stringify with BOTH arrayFormat: 'comma' AND encodeValuesOnly: true options simultaneously - both are non-default and must be explicitly configured by developers. The input data passed to stringify must contain an array with at least one null or undefined element. This vulnerability is reachable from JSON request bodies in REST APIs (application/json content type) or from application code that constructs arrays from user input, but NOT from standard HTML form submissions which produce string values or omitted fields rather than literal null. Attack vector is network (AV:N) with no authentication required (PR:N based on CVSS vector), but attack technique is present (AT:P) due to the dual configuration requirement. Limits on exploitation: the synchronous throw is typically caught by Node.js framework error boundaries (Express, Fastify, Koa, hapi), returning HTTP 500 for the affected request without terminating the worker process, so impact is limited to denial of service for individual requests rather than full application crash in standard web application deployments. |
| Impact | Real-world risk is moderate and context-dependent. CVSS 4.0 score of 6.3 (AV:N/AC:L/AT:P/PR:N/UI:N/VA:L) correctly reflects network accessibility with low complexity but limited availability impact - the attack complexity metric AT:P (Attack Complexity: Present) captures the requirement for two non-default options to be enabled simultaneously. No EPSS score, KEV listing, or SSVC data provided, but GitHub commit evidence confirms vendor patch released February 2025 in v6.15.2. The vulnerability requires application code to use both arrayFormat: 'comma' AND encodeValuesOnly: true together - both are non-default settings that must be explicitly configured. Standard HTML form submissions cannot trigger this (forms produce strings, not null values), limiting the attack surface to JSON APIs or code constructing arrays from parsed user input. In typical Node.js web frameworks (Express, Fastify, Koa, hapi), the synchronous throw is caught by framework error boundaries and returns HTTP 500 to the affected request without killing the worker process - subsequent requests continue normally. The 'process crash' scenario only applies to call sites outside request handlers (background jobs, startup paths, stream pipelines) or deployments that explicitly disable framework error handling. Given the narrow configuration requirements and automatic recovery in common deployments, this is lower priority than the CVSS score alone suggests, though teams using comma+encodeValuesOnly together should patch immediately. |
| Exploit ScenarioDerived | An attacker sends a crafted JSON POST request to an API endpoint that uses qs.stringify with arrayFormat: 'comma' and encodeValuesOnly: true to serialize response data. The JSON payload includes an array parameter with a null element, for example {"filters": [null, "active"]}. When the application processes this input and passes the deserialized object to qs.stringify, the library throws an uncaught TypeError. The web framework's error boundary catches the exception and returns HTTP 500 to the attacker, confirming the vulnerability. The attacker can repeatedly trigger 500 errors for affected endpoints, causing denial of service for legitimate users of those API routes. Proof-of-concept code is available in the GitHub security advisory demonstrating the exact throw condition. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – May 17, 2026
The qs Node.js library (versions 6.11.1 through 6.15.1) crashes with a synchronous TypeError when stringify is called with both arrayFormat: 'comma' and encodeValuesOnly: true on arrays containing null or undefined elements. Applications using these non-default options together will experience request failures (typically 500 errors in web frameworks) when processing user input with null array values. The vulnerability was introduced in commit 4c4b23d (PR #463, January 2023) and patched in v6.15.2 (commit 21f80b3). No public exploit or CISA KEV listing identified at time of analysis, though exploitation requires only crafting JSON input with null array elements.
RemediationAI
Upgrade to qs v6.15.2 or later, released February 2025, which applies the fix from commit 21f80b3. The patch wraps array elements in a null-checking lambda before encoding: obj = utils.maybeMap(obj, function (v) { return v == null ? v : encoder(v); }) so null/undefined values pass through unchanged to the join step. See vendor advisory at https://github.com/ljharb/qs/security/advisories/GHSA-q8mj-m7cp-5q26 for complete patch details. If immediate upgrade is not feasible, apply one of these workarounds with noted trade-offs: (1) Remove encodeValuesOnly: true from stringify calls and accept that parameter names will be percent-encoded (changes output format but eliminates crash). (2) Pre-filter arrays to remove null/undefined before passing to qs.stringify using array.filter(v => v != null) (adds processing overhead and silently drops null values that may have semantic meaning). (3) Switch to a different arrayFormat option like 'brackets' or 'indices' (changes query string format, may break API consumers expecting comma-delimited arrays). (4) Add application-level try-catch around qs.stringify calls to convert TypeError to controlled error response (does not prevent 500 errors, only allows custom error handling). Option 1 is safest if comma-delimited output is not strictly required.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in npm
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The qs library implements RFC 3986 query string encoding/decoding for Node.js applications. The vulnerable code path occurs in lib/stringify.js:145 when the comma array format (which serializes arrays as a=1,2,3 instead of a[]=1&a[]=2) is combined with encodeValuesOnly mode (which skips encoding parameter names). In this configuration, the code calls utils.maybeMap(obj, encoder) which attempts to read the length property of each array element before joining them with commas. The encoder function (utils.encode at lib/utils.js:195) accesses str.length without null guards, triggering 'Cannot read properties of null (reading length)' when encountering null or undefined. The bug represents CWE-476 (NULL Pointer Dereference) adapted to JavaScript's dynamic typing - attempting to access properties on null/undefined values. The existing null-handling options (skipNulls, strictNullHandling) are evaluated later in the processing pipeline and never execute because the synchronous throw occurs first. This is the same vulnerability class previously fixed in the filter-array path (commit 0c180a4), indicating a pattern of incomplete null validation across different code branches handling the comma array format.
Know when Node.js gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
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
Primary rating from Vendor (7ffcee3d-2c14-4c3e-b844-86c6a321a158).
CVSS VectorVendor: 7ffcee3d-2c14-4c3e-b844-86c6a321a158
DescriptionCVE.org
Summary
qs.stringify throws TypeError when called with arrayFormat: 'comma' and encodeValuesOnly: true on an array containing null or undefined. The throw is synchronous and not handled by any of qs's null-related options (skipNulls, strictNullHandling).
Details
In the comma + encodeValuesOnly branch, lib/stringify.js:145 mapped the array through the raw encoder before joining:
obj = utils.maybeMap(obj, encoder);
utils.encode (lib/utils.js:195) reads str.length with no null guard, so a null or undefined element throws TypeError. skipNulls and strictNullHandling are both checked in the per-element loop below this line and never get a chance to run.
Same class of bug as the filter-array path fixed in 0c180a4. The vulnerable shape of the comma + encodeValuesOnly branch was introduced in 4c4b23d ("encode comma values more consistently", PR #463, 2023-01-19), first released in v6.11.1.
PoC
const qs = require('qs');
qs.stringify({ a: [null, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true });
qs.stringify({ a: [undefined, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true });
qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true });
// TypeError: Cannot read properties of null (reading 'length')
// at encode (lib/utils.js:195:13)
// at Object.maybeMap (lib/utils.js:322:37)
// at stringify (lib/stringify.js:145:25)
Fix
lib/stringify.js:145, applied in 21f80b3 on main and released as v6.15.2:
- obj = utils.maybeMap(obj, encoder);
+ obj = utils.maybeMap(obj, function (v) {
+ return v == null ? v : encoder(v);
+ });
null and undefined now pass through maybeMap unchanged and reach the join(',') step as-is. For { a: [null, 'b'] } this produces a=,b, matching the non-encodeValuesOnly comma path (which already joins before encoding and produces a=%2Cb for the same input). Single-element [null] arrays still collapse via the existing obj.join(',') || null and remain subject to skipNulls / strictNullHandling in the main loop.
Affected versions
>=6.11.1 <6.15.2 - fixed in v6.15.2.
The vulnerable code shape was introduced in 4c4b23d and first shipped in v6.11.1. Earlier versions - including all of 6.7.x, 6.8.x, 6.9.x, 6.10.x, and 6.11.0 - implemented the comma + encodeValuesOnly path differently (joining before encoding) and are not affected. Empirically verified across released versions.
Impact
Application code that calls qs.stringify with both arrayFormat: 'comma' and encodeValuesOnly: true (both non-default) on input that may contain a null or undefined array element will throw synchronously instead of producing a query string. In a typical Node.js HTTP framework (Express, Fastify, Koa, hapi) the sync throw is caught by the framework's error boundary and the affected request returns a 500; the worker process does not exit and subsequent requests are unaffected. The "kills the worker process" framing applies only to call sites outside a request-handler error boundary (background jobs, startup paths, stream pipelines) or to deployments with framework error handling explicitly disabled.
The vulnerable input is a null or undefined entry inside an array; this is reachable from JSON request bodies or from application code constructing arrays from user input, but not from standard HTML form submissions (which produce strings or omitted fields, not literal null).
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
A null pointer dereference occurs when a program attempts to access memory through a pointer that has been set to NULL (address 0x0).
Denial of Service attacks render applications or systems unavailable by overwhelming resources or triggering failure conditions.
Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation
A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could
FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote
Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour
Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t
Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc
An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi
Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin
A vulnerability in NuPoint Messenger (NPM) of Mitel MiCollab through 9.8.0.33 allows an unauthenticated attacker to cond
GHSA-q8mj-m7cp-5q26
NVD
CVE.org
EPSS
Vulnrichment
VulDB
Exploit-DB