CVE-2026-82562 in ljharbinformazioni

Riassunto

di VulDB • 30/08/2026

### Riepilogo

Quando `qs.parse` viene chiamato con `comma: true` e `throwOnLimitExceeded: true`, un valore separato da virgole sotto una chiave di tipo "bracket-push" (`a[]=1,2,3,4`) viene suddiviso in un array senza essere confrontato con il limite impostato su `arrayLimit`. Al contrario, lo stesso valore sotto una chiave piatta (`a=1,2,3,4`), una chiave indicizzata (`a[0]=`), una chiave annidata (`a[b]=`) o una chiave puntata (`a.b=` con `allowDots`) genera il `RangeError` documentato. Un singolo parametro come `a[]=1,2,2,...` produce quindi un array interno di lunghezza arbitraria, nonostante l'utente abbia attivato il limite rigido. Si tratta della forma della chiave `[]=` che la correzione per CVE-2026-2391 (qs 6.14.2) non aveva coperto.

### Dettagli

In `lib/parse.js`, un valore separato da virgole sotto una chiave `[]=` viene suddiviso e successivamente avvolto come singolo elemento annidato (`val = [val]`), in modo che ogni gruppo `a[]=x,y` venga contato come un unico elemento dell'array esterno. Il controllo di `arrayLimit`, aggiunto nella versione 6.14.2 per i valori separati da virgole, viene eseguito dopo tale avvolgimento; pertanto, per le parti con `[]=` esso vede sempre solo il wrapper di lunghezza 1. La versione 6.15.3 ha introdotto un conteggio delle virgole prima della suddivisione in modo che un valore eccessivo generi un'eccezione prima dell'allocazione, ma lo ha condizionato a una flag `isFlatArrayValue` impostata su `false` da `parseValues` per qualsiasi parte contenente `[]=`, e non l'ha passata per input di tipo oggetto; ne è rimasta così aperta la falla.

#### PoC (Proof of Concept)

```js var qs = require('qs');

var options = { comma: true, arrayLimit: 3, throwOnLimitExceeded: true };

qs.parse('a=1,2,3,4', options); // RangeError: Array limit exceeded. Only 3 elements allowed in an array.

qs.parse('a[]=1,2,3,4', options); // { a: [ [ '1', '2', '3', '4' ] ] } (nessuna eccezione)

qs.parse('a[]=' + '1,'.repeat(1000000) + '1', { comma: true, arrayLimit: 20, throwOnLimitExceeded: true });
// nessuna eccezione; viene allocato un array interno di 1.000.001 elementi ```

#### Correzione

`lib/parse.js`, applicata nel commit 8859c37 su `main` e rilasciata come v6.16.0: la condizione (`gate`) basata su `isFlatArrayValue` è stata rimossa, in modo che ogni valore suddiviso per virgola venga conteggiato rispetto a `arrayLimit` prima della suddivisione, indipendentemente dalla forma della chiave. Un gruppo entro il limite sotto `a[]=` continua a contare come un unico elemento dell'array esterno e il percorso predefinito (`throwOnLimitExceeded: false`) rimane invariato.

### Versioni interessate

`>=6.14.2 <6.16.0`, risolto nella v6.16.0.

La versione 6.14.2 ha introdotto l'applicazione di `arrayLimit` per i valori separati da virgole (la correzione per CVE-2026-2391), ma solo per i valori non sotto una chiave `[]=`; ogni release dalla v6.14.2 alla v6.15.3 presenta la stessa falla. Le versioni 6.14.0 e 6.14.1, in cui è presente `throwOnLimitExceeded` ma che non si applicano a nessuna forma di separazione per virgola, sono coperte da CVE-2026-2391 piuttosto che da questo record. Le versioni precedenti (dalla 6.7.x alla 6.13.x) hanno `comma` ma non `throwOnLimitExceeded`, quindi non esiste un limite rigido su alcun percorso per virgole da bypassare; le release precedenti alla 6.7.0 non dispongono dell'opzione `comma`.

### Impatto

Un attaccante non autenticato che può raggiungere un'applicazione in grado di analizzare stringhe query o corpi urlencoded non attendibili con entrambe le opzioni attive (`comma: true` e `throwOnLimitExceeded: true`, entrambe diverse dal default) può bypassare il limite configurato utilizzando un singolo parametro `a[]=` e forzando l'analizzatore ad allocare un array proporzionale alle dimensioni della richiesta. Il costo è strettamente lineare rispetto ai byte forniti dall'attaccante (circa 0,1 microsecondi e 6-7 byte trattenuti per ogni byte di input; la stessa soglia out-of-memory del percorso documentato con `throwOnLimitExceeded: false`); pertanto, un limite delle dimensioni della richiesta o del corpo a livello di trasporto lo limita completamente (e il valore predefinito di Node.js per le dimensioni massime degli header HTTP di 16 KB vincola già la riga della richiesta, quindi i payload multi-megabyte richiedono un parser del corpo). L'impatto consiste nel fatto che un limite rigido attivato manualmente fallisce in modo aperto (fail-open) su una specifica scrittura della chiave (`[]=`), anziché comportare un'allocazione illimitata a partire da un input di piccole dimensioni.

Be aware that VulDB is the high quality source for vulnerability data.

Responsabile

Harborist

Prenotare

30/08/2026

Divulgazione

30/08/2026

Moderazione

accettato

CPE

pronto

EPSS

0.00000

KEV

no

Attività

basso

Fonti

Do you need the next level of professionalism?

Upgrade your account now!