Skip to main content

qs CVE-2026-110816

| EUVDEUVD-2026-101710 MEDIUM
Uncaught Exception (CWE-248)
2026-10-14 7ffcee3d-2c14-4c3e-b844-86c6a321a158
6.3
CVSS 4.0 · Vendor: 7ffcee3d-2c14-4c3e-b844-86c6a321a158
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Send request with crafted toString/prototype key
  2. Delivery
    qs.parse(allowPrototypes) retains object array element
  3. Exploit
    app re-serializes via qs.stringify comma format
  4. Execution
    coercion throws uncaught TypeError
  5. Impact
    request returns 500 or process exits

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A10:2025 - Mishandling of Exceptional Conditions
ASVS 5.0
V16 - Security Logging and Error Handling Exception handling completeness
Exploitation Conditions

Exploitation requires the application to re-serialize attacker-influenced data by calling qs.stringify with the NON-DEFAULT arrayFormat:'comma' option (the default 'indices' and the 'brackets'/'repeat' formats are not affected), running an affected qs version 6.7.0 through 6.16.0. The attacker-controlled data must contain an array element that cannot be string-coerced - an object with an own non-callable toString (e.g. {"toString":"x"}) or a null-prototype object. Such elements reach qs.stringify when the app parses input with qs.parse using allowPrototypes:true (the default for Express 4's query parser, Express 5's extended parser, and body-parser's urlencoded({extended:true})) or plainObjects:true, or when it serializes a parsed JSON body. LIMITING FACTORS: default qs.parse options strip the toString key and do NOT throw; no user interaction or authentication is needed, but the non-default comma serialization path must exist in the application. The impact is bounded to a caught 500 error within a framework error boundary; full process termination only occurs where the call runs outside an error boundary (async Express 4 handler yielding an unhandled rejection, or a bare http handler).

Impact

This is a genuine but modest-severity denial-of-service issue (CWE-248, uncaught exception), not a high-impact flaw. The vendor CVSS 4.0 vector (AV:N/AC:L/AT:P/PR:N/UI:N, VC:N/VI:N/VA:L = 6.3) correctly captures the shape: network-reachable and unauthenticated (PR:N), but with an attack requirement (AT:P) and only limited availability impact (VA:L), no confidentiality or integrity impact. The signals are internally consistent and point to low-to-medium real-world risk: publicly available exploit code exists (a working PoC is embedded in the GHSA advisory), but there is NO EPSS score in the provided data and the CVE is NOT listed in CISA KEV, so there is no evidence of active or widespread exploitation. The AT:P requirement is the key limiter - exploitation depends on the application re-serializing attacker-influenced data with qs.stringify using the non-default arrayFormat:'comma' option, so the raw 'AV:N/PR:N' profile overstates practical exposure. The most common outcome is a caught 500 error self-limited to a single request; the process-crash outcome only occurs outside a framework error boundary (e.g. an async Express 4 handler or bare http handler), making worst-case impact dependent on application error handling rather than on qs itself. Net: patch on the normal maintenance cycle - this is not an emergency unless you run the specific vulnerable comma re-serialization pattern outside an error boundary.

Exploit ScenarioDerived

An unauthenticated attacker sends an HTTP request containing a crafted parameter such as 'a[0][toString]=x' to an Express/body-parser application (which parse with allowPrototypes:true by default). If the app later rebuilds a query string from the parsed data using qs.stringify with arrayFormat:'comma' - for example to construct a redirect or an upstream request URL - the join/String() coercion of the prototype-key object throws a synchronous TypeError. A working PoC is published in the GHSA advisory; because AC is low and no authentication or user interaction is needed, triggering it is trivial wherever the vulnerable serialization pattern exists.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 15, 2026

Denial of service in the qs npm query-string library (6.7.0 through 6.16.0) lets an unauthenticated remote attacker force a synchronous TypeError in any application that re-serializes attacker-influenced data with qs.stringify and the non-default option arrayFormat: 'comma'. The crash is triggered when an array element cannot be string-coerced, such as an object with an own non-callable toString ({"toString":"x"}) or a null-prototype object; such elements survive parsing when the application uses qs.parse with allowPrototypes or plainObjects enabled (the defaults for Express 4's query parser, Express 5's extended parser, and body-parser's urlencoded({extended:true})), or when a parsed JSON body is re-serialized. Publicly available proof-of-concept code exists in the vendor advisory, and the reported CVSS v4 score is 6.3, although an independent CVSS 3.1 assessment rates it lower (AC:H, availability impact Low) because the non-default comma serialization path must exist in the target application; realistic impact is a framework-caught HTTP 500, with full process termination only where the call runs outside an error boundary. Vendor-released patch: 6.16.1.

RemediationAI

Upgrade the qs dependency to 6.16.1 or later (fix commit a952e7519338ef0cfb25694a2988848f93333727; advisory https://github.com/ljharb/qs/security/advisories/GHSA-6pq8-jhm2-2vcw), and run npm audit or a lockfile scan to confirm no transitive copy remains pinned to 6.7.0-6.16.0 - a common complication is that Express and body-parser pull qs transitively, so an npm overrides/resolutions entry or a direct dependency bump may be required before the patched version is actually resolved. If immediate upgrading is not possible, the highest-value workaround is to stop using arrayFormat: 'comma' in any qs.stringify call that handles request-derived or JSON-parsed data: the default 'indices' format plus 'brackets' and 'repeat' are unaffected, and the only downside is a change in the emitted query-string shape for list parameters, which may break peers that expect comma-delimited lists. Wrapping the re-serialization call in try/catch and falling back to a sanitized or omitted query string prevents the exception from propagating at the cost of silently degrading that output. Because the crash requires an element that cannot be string-coerced, sanitizing inputs before serialization also helps: re-map or JSON-clone parsed objects so array elements are primitives, or avoid qs.parse with allowPrototypes: true and plainObjects: true - note that switching Express's query parser to 'simple' loses nested query-object parsing, and body-parser's extended:false loses nested body fields, both of which can break existing clients. Finally, ensure the failure path is contained: keep qs.stringify calls inside framework error boundaries and prefer wrapping them in async handlers rather than letting them sit bare, since an async Express 4 handler turns the throw into an unhandled rejection that can terminate the process, whereas a caught throw only produces a 500 response for the affected request.

Affected VersionsENISA

qs 6.7.0 <6.16.1

Affected Packages

euvd qs fix: 6.16.1

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

qs is a widely used JavaScript query-string parser/serializer underpinning query parsing in Express 4, Express 5 and body-parser. Two code sites are involved. In lib/stringify.js, the arrayFormat: 'comma' branch collapses an array with Array.prototype.join(','), and in lib/utils.js the encodeValuesOnly path first passes each element through String(str). Both operations rely on JavaScript's ToPrimitive coercion, which for a plain object calls its own toString if callable; an object whose own toString property exists but is not callable (e.g. produced by JSON.parse of {"a":[{"toString":"x"}]} or by qs.parse with allowPrototypes:true) skips that step, falls through to Object.prototype.valueOf (which returns the object itself), and throws TypeError: Cannot convert object to primitive value. Null-prototype objects (produced by qs.parse with plainObjects:true) fail the same way because they lack a prototype-supplied toString. The issue is classified CWE-248 (Uncaught Exception) and maps to a Denial of Service class; affected code paths are limited to arrayFormat: 'comma' because the indices, brackets and repeat formats walk into object elements instead of coercing them. The fix in commit a952e7519338ef0cfb25694a2988848f93333727 adds a utils.toCoercible helper that detects objects without a callable toString, substitutes a primitive valueOf result when one exists, otherwise falls back to Object.prototype.toString so the element renders as '[object Object]'; nested arrays are walked the way join walks them and cyclically nested arrays join their cycle as an empty string. Inputs that did not previously throw serialize identically, and a toString or valueOf that itself throws still propagates. No CPE identifiers were supplied with this record; the affected component is the npm package qs, tracked by ENISA EUVD as EUVD-2026-101710 for versions 6.7.0 < 6.16.1.

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

Vendor (7ffcee3d-2c14-4c3e-b844-86c6a321a158) PRIMARY 6.3 MEDIUM
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
vuln.today AI 3.7 LOW

Network-reachable and unauthenticated (AV:N/PR:N), but the non-default comma-serialization precondition beyond attacker control warrants AC:H; only limited availability impact, no C/I.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
4.0 AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
Red Hat 5.3 MEDIUM

Primary rating from Vendor (7ffcee3d-2c14-4c3e-b844-86c6a321a158).

CVSS VectorVendor: 7ffcee3d-2c14-4c3e-b844-86c6a321a158

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
Present
Privileges Required
None
User Interaction
None
Vulnerable system: Confidentiality
None
Vulnerable system: Integrity
None
Vulnerable system: Availability
Low
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

2
Patch available
Oct 14, 2026 - 23:04 EUVD
CVE Published
Oct 14, 2026 - 22:17 cve.org
MEDIUM 6.3

DescriptionCVE.org

Summary

qs.stringify with arrayFormat: 'comma' throws TypeError: Cannot convert object to primitive value when an array element cannot be coerced to a string, such as an object with an own non-callable toString ({ "toString": "x" }) or a null-prototype object. The comma format joins array elements with Array.prototype.join and, under encodeValuesOnly, first passes each element through String() in utils.encode; neither guards against an element whose string coercion fails.

Details

In lib/stringify.js, the comma branch collapses the array with obj.join(','). For an element whose own toString is not callable, ToPrimitive skips it, falls through to Object.prototype.valueOf (which returns the object itself), and throws. Under encodeValuesOnly: true, the same element first reaches String(str) in utils.encode (lib/utils.js) and throws there. Nested arrays ({ "a": [[{ "toString": "x" }]] }) throw the same way, through Array.prototype.toString. The indices, brackets, and repeat formats walk into object elements instead of coercing them, and are not affected.

Such elements can come from untrusted input. JSON.parse produces { "a": [{ "toString": "x" }] } with no qs option involved. qs.parse("a[0][toString]=x", { allowPrototypes: true }) keeps the toString key, and qs.parse("a[][b]=c", { plainObjects: true }) produces a null-prototype element; the default parse options drop toString and produce ordinary objects, which do not throw. Express 4's default query parser, Express 5's extended query parser, and body-parser's urlencoded({ extended: true }) all call qs.parse with allowPrototypes: true.

PoC
js



var qs = require("qs");



qs.stringify(JSON.parse("{\"a\":[{\"toString\":\"x\"}]}"), { arrayFormat: "comma" });



qs.stringify(qs.parse("a[0][toString]=x", { allowPrototypes: true }), { arrayFormat: "comma" });



qs.stringify(qs.parse("a[][b]=c", { plainObjects: true }), { arrayFormat: "comma", encodeValuesOnly: true });



// TypeError: Cannot convert object to primitive value


Fix

Applied in a952e75 on main and released as v6.16.1: an element whose string coercion would fail is coerced to its primitive valueOf, if any, or else to Object.prototype.toString, so it renders as [object Object], the same as any other object element already does under the comma format. Nested arrays are walked the way join walks them. Every input that did not previously throw serializes exactly as before, and a toString or valueOf that itself throws still propagates.

Affected versions

>=6.7.0 <6.16.1, fixed in v6.16.1.

The join path was introduced with the comma format in b84acba and first shipped in v6.7.0; v6.6.x and earlier ignore arrayFormat: 'comma' and are not affected. The encodeValuesOnly String() site was introduced in 4c4b23d (v6.11.1); before that, the same input throws at join. Every release from v6.7.0 through v6.16.0 is affected.

Impact

An unauthenticated request can make any code path that re-serializes attacker-influenced data with qs.stringify and arrayFormat: 'comma' (for example, rebuilding a query string from req.query for a redirect or an upstream request, or serializing a parsed JSON body) throw synchronously. In a typical Node.js HTTP framework the throw is caught by the framework error boundary and the affected request returns a 500; the process survives and other requests are unaffected. Where the call runs outside an error boundary, such as an async Express 4 handler (where the throw becomes an unhandled promise rejection) or a bare http request handler, the process exits, so the impact in that case depends on the application error handling rather than on qs. The default arrayFormat (indices) is not affected.

Threat Intelligence Overview

EPSS Score
0.3%
Top 78% exploitable
Prevalence
Ubiquitous
qs is a core transitive dependency of Express/body-parser across the Node ecosystem
Data Quality
5 sources
Confidence: Medium
EUVD NVD CVE.org EPSS Vulnrichment Vendor GitHub VulDB

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.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
Yes
Human Impact· derived
High
Technical Impact
Partial

Priority Score

32
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +32
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0
CVE-2025-68613 HIGH POC
8.8 Dec 19

Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation

CVE-2024-41713 CRITICAL POC
9.1 Oct 21

A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2023-44487 HIGH POC
7.5 Oct 10

Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-0224 HIGH POC
7.4 Jun 05

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

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

Vendor StatusVendor

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy