Where
-Infinity
0
Severity
8.7
Input Validation
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

The arrayLimit option in qs does not enforce limits for bracket notation (a[]=1&a[]=2), allowing attackers to cause denial-of-service via memory exhaustion. Applications using arrayLimit for DoS protection are vulnerable.

Details

The arrayLimit option only checks limits for indexed notation (a[0]=1&a[1]=2) but completely bypasses it for bracket notation (a[]=1&a[]=2).

Vulnerable code (lib/parse.js:159-162): javascript if (root === '[]' && options.parseArrays) { obj = utils.combine([], leaf); // No arrayLimit check }

Working code (lib/parse.js:175): javascript else if (index <= options.arrayLimit) { // Limit checked here obj = []; obj[index] = leaf; }

The bracket notation handler at line 159 uses utils.combine([], leaf) without validating against options.arrayLimit, while indexed notation at line 175 checks index <= options.arrayLimit before creating arrays.

PoC

Test 1 - Basic bypass: bash npm install qs

javascript const qs = require('qs'); const result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 }); console.log(result.a.length); // Output: 6 (should be max 5)

Test 2 - DoS demonstration: javascript const qs = require('qs'); const attack = 'a[]=' + Array(10000).fill('x').join('&a[]='); const result = qs.parse(attack, { arrayLimit: 100 }); console.log(result.a.length); // Output: 10000 (should be max 100)

Configuration: - arrayLimit: 5 (test 1) or arrayLimit: 100 (test 2) - Use bracket notation: a[]=value (not indexed a[0]=value)

Impact

Denial of Service via memory exhaustion. Affects applications using qs.parse() with user-controlled input and arrayLimit for protection.

Attack scenario: 1. Attacker sends HTTP request: GET /api/search?filters[]=x&filters[]=x&...&filters[]=x (100,000+ times) 2. Application parses with qs.parse(query, { arrayLimit: 100 }) 3. qs ignores limit, parses all 100,000 elements into array 4. Server memory exhausted → application crashes or becomes unresponsive 5. Service unavailable for all users

Real-world impact: - Single malicious request can crash server - No authentication required - Easy to automate and scale - Affects any endpoint parsing query strings with bracket notation

Suggested Fix

Add arrayLimit validation to the bracket notation handler. The code already calculates currentArrayLength at line 147-151, but it's not used in the bracket notation handler at line 159.

Current code (lib/parse.js:159-162): javascript if (root === '[]' && options.parseArrays) { obj = options.allowEmptyArrays && (leaf === '' || (options.strictNullHandling && leaf === null)) ? [] : utils.combine([], leaf); // No arrayLimit check }

Fixed code: javascript if (root === '[]' && options.parseArrays) { // Use currentArrayLength already calculated at line 147-151 if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) { throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.'); } // If limit exceeded and not throwing, convert to object (consistent with indexed notation behavior) if (currentArrayLength >= options.arrayLimit) { obj = options.plainObjects ? { proto: null } : {}; obj[currentArrayLength] = leaf; } else { obj = options.allowEmptyArrays && (leaf === '' || (options.strictNullHandling && leaf === null)) ? [] : utils.combine([], leaf); } }

This makes bracket notation behaviour consistent with indexed notation, enforcing arrayLimit and converting to object when limit is exceeded (per README documentation).

1 / 5
Source: GitHub
First published (updated )
Severity
7
Input Validation

Improper Input Validation vulnerability in qs (parse modules) allows HTTP DoS.This issue affects qs: < 6.14.1.

SummaryThe arrayLimit option in qs does not enforce limits for bracket notation (a[]=1&a[]=2), allowing attackers to cause denial-of-service via memory exhaustion. Applications using arrayLimit for DoS protection are vulnerable.

DetailsThe arrayLimit option only checks limits for indexed notation (a[0]=1&a[1]=2) but completely bypasses it for bracket notation (a[]=1&a[]=2).

Vulnerable code (lib/parse.js:159-162):

if (root === '[]' && options.parseArrays) { obj = utils.combine([], leaf); // No arrayLimit check }

Working code (lib/parse.js:175):

else if (index <= options.arrayLimit) { // Limit checked here obj = []; obj[index] = leaf; }

The bracket notation handler at line 159 uses utils.combine([], leaf) without validating against options.arrayLimit, while indexed notation at line 175 checks index <= options.arrayLimit before creating arrays.

PoCTest 1 - Basic bypass:

npm install qs

const qs = require('qs'); const result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 }); console.log(result.a.length); // Output: 6 (should be max 5)

Test 2 - DoS demonstration:

const qs = require('qs'); const attack = 'a[]=' + Array(10000).fill('x').join('&a[]='); const result = qs.parse(attack, { arrayLimit: 100 }); console.log(result.a.length); // Output: 10000 (should be max 100)

Configuration:

arrayLimit: 5 (test 1) or arrayLimit: 100 (test 2) Use bracket notation: a[]=value (not indexed a[0]=value)

ImpactDenial of Service via memory exhaustion. Affects applications using qs.parse() with user-controlled input and arrayLimit for protection.

Attack scenario:

Attacker sends HTTP request: GET /api/search?filters[]=x&filters[]=x&...&filters[]=x (100,000+ times) Application parses with qs.parse(query, { arrayLimit: 100 }) qs ignores limit, parses all 100,000 elements into array Server memory exhausted → application crashes or becomes unresponsive Service unavailable for all users Real-world impact:

Single malicious request can crash server No authentication required Easy to automate and scale Affects any endpoint parsing query strings with bracket notation

First published (updated )
Severity
6.3
EPSS
0.02%
Input Validation
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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

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.

1 / 3
Source: IBM
First published (updated )
Severity
6.3
EPSS
0.36%
Null Pointer Dereference
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

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:

js

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

js

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:

diff

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

1 / 3
Source: IBM
First published (updated )

This is the daily security digest covering confirmed npm, PyPI, and supply-chain security threats detected in the past 24 hours. A total of 14 threats have been identified across various ecosystems, including active credential harvesting campaigns.

📊 Threat Summary

|Package(s)|Ecosystem|Severity|CVE|Vulnerability| |:-|:-|:-|:-|:-| |u/cap-js/sqlite, postgres, db-service|npm|CRITICAL|CVE-2026-46421|Credential harvesting / Self-propagation| |u/beproduct/nestjs-auth|npm|CRITICAL|CVE-2026-46412|Mini Shai-Hulud worm payload| |guardrails-ai|PyPI|CRITICAL|CVE-2026-45758|Supply chain compromise| |Parse Server|npm|HIGH|CVE-2026-47138|DoS via header regex backtracking| |qs|npm|HIGH|CVE-2026-8723|Remotely triggerable DoS| |u/libp2p/gossipsub|npm|HIGH|CVE-2026-46679|Memory DoS (Subscription flood)| |u/libp2p/kad-dht|npm|HIGH|CVE-2026-45783|Disk exhaustion (Unvalidated PUT)| |SQLFluff|PyPI|HIGH|CVE-2026-46374|DoS via Resource Exhaustion| |Diffusers|ai-ml|HIGH|CVE-2026-45804|TOCTOU Remote Code Execution| |lmdeploy|ai-ml|HIGH|CVE-2026-46517|Unsafe remote-code load path| |Crawlee for Python|PyPI|HIGH|CVE-2026-46497|SSRF via sitemap-derived URLs| |SillyTavern|ai-ml|HIGH|CVE-2026-46372|SSRF in SearXNG Search Proxy| |samlify|npm|HIGH|CVE-2026-46490|XML Injection / Privilege Escalation| |js-cookie|npm|HIGH|CVE-2026-46625|Prototype hijack / Cookie injection|

🚨 CRITICAL Alerts (Immediate Action Required)

1. u/cap-js ecosystem compromise (CVE-2026-46421)

Threat: Compromised versions of u/cap-js/sqlite, u/cap-js/postgres, and u/cap-js/db-service were published to harvest credentials and self-propagate. Action: Upgrade immediately (sqlite \>= 2.4.0, postgres \>= 2.3.0, db-service \>= 2.10.2). Assume all local credentials are compromised if you installed the malicious versions.

2. u/beproduct/nestjs-auth worm (CVE-2026-46412)

Threat: Malicious versions containing payloads from the Mini Shai-Hulud npm supply-chain worm campaign were published. Action: Remove and reinstall dependencies. Audit for signs of compromise if installed during the affected window (v0.1.2 - 0.1.19).

3. guardrails-ai compromise (CVE-2026-45758)

Threat: A malicious version of guardrails-ai (0.10.1) was published to PyPI. It has been quarantined. Action: Uninstall guardrails-ai==0.10.1 and reinstall a known good version.

⚠️ HIGH Severity Highlights

Denial of Service (DoS) Wave: Several major packages are vulnerable to crashing today. Parse Server (CVE-2026-47138) can be taken down pre-auth via a regex backtracking attack in the client version header. qs (CVE-2026-8723) will crash on specific null/undefined arrays. u/libp2p packages are vulnerable to both memory and disk exhaustion attacks. AI Toolchain Remote Code Execution: Both Diffusers (CVE-2026-45804) and lmdeploy (CVE-2026-46517) have vulnerabilities bypassing trustremotecode guardrails, allowing arbitrary remote code execution on model fetch. SSRF & Injection: Crawlee for Python and SillyTavern both suffer from SSRF vulnerabilities requiring configuration updates. samlify is vulnerable to XML injection leading to privilege escalation, and js-cookie is vulnerable to a prototype hijacking attack.

Automated daily digest, created via https://github.com/Deam0on/wakellm - feedback welcome. Stay safe out there!

First published (updated )
Social
reddit

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203