Regola
Proteggiti dalle espressioni regolari lente.
Le espressioni regolari con quantificatori annidati
o pattern ambigui possono causare
un backtracking catastrofico e problemi di prestazioni.
Linguaggi supportati: 45+Introduzione
Le espressioni regolari possono bloccare la tua applicazione per secondi o minuti se ricevono l'input giusto. Il backtracking catastrofico si verifica quando i motori regex esplorano percorsi in crescita esponenziale mentre cercano di far corrispondere un pattern. Una regex come (a+)+b impiega microsecondi per trovare la corrispondenza con un input valido, ma può richiedere ore per rifiutare una stringa di 'a' senza una 'b' finale. Gli attaccanti sfruttano questa vulnerabilità tramite attacchi di tipo Regular Expression Denial of Service (ReDoS), inviando input appositamente predisposti che fanno sì che il motore regex consumi il 100% della CPU fino allo scadere dei timeout delle richieste o all'arresto anomalo del processo.
Perché è importante
Implicazioni sulla sicurezza (attacchi ReDoS): un utente malintenzionato può paralizzare la tua applicazione con una singola richiesta contenente un input manipolato. I pattern di convalida delle email e di analisi degli URL sono bersagli comuni. A differenza dei tradizionali attacchi DoS che richiedono larghezza di banda, il ReDoS necessita solo di payload piccolissimi.
Degradazione delle prestazioni: il normale input dell'utente può innescare un backtracking catastrofico, facendo impennare i tempi di risposta da millisecondi a secondi. Questo crea una latenza imprevedibile e difficile da debuggare, poiché si manifesta solo con specifici pattern di input.
Incidenti in produzione: una regex vulnerabile blocca il ciclo degli eventi in Node.js o consuma le risorse del pool di thread. Con l'accumularsi delle richieste, la memoria aumenta e il sistema non risponde più. Nei microservizi, una singola regex vulnerabile propaga i guasti ai servizi dipendenti.
Difficoltà di rilevamento: i pattern che funzionano perfettamente nei test con input brevi diventano esponenzialmente più lenti con input più lunghi. La vulnerabilità spesso passa inosservata fino alla produzione, richiedendo un deployment d'emergenza durante un incidente attivo.
Esempi di codice
❌ Non conforme:
function validateEmail(email) {
const regex = /^([a-zA-Z0-9_\-\.]+)+@([a-zA-Z0-9_\-\.]+)+\.([a-zA-Z]{2,5})$/;
return regex.test(email);
}
function extractURLs(text) {
const regex = /(https?:\/\/)?([\w\-])+\.(\w+)+([\w\-\.,@?^=%&:/~\+#]*)+/g;
return text.match(regex);
}
Perché non è sicuro: I quantificatori annidati ([a-zA-Z0-9_\\-\\.]+)+ creano un backtracking esponenziale. Per un'email come aaaaaaaaaaaaaaaaaaaaaaaaa!, il motore regex tenta innumerevoli combinazioni prima di fallire. La regex dell'URL presenta molteplici quantificatori annidati che aggravano il problema, rendendolo facilmente sfruttabile con input costituiti da lunghe stringhe di caratteri validi privi della struttura attesa.
✅ Conforme:
function validateEmail(email) {
const regex = /^[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,5}$/;
return regex.test(email);
}
function extractURLs(text) {
const regex = /https?:\/\/[\w\-]+\.[\w\-]+(?:[\w\-\.,@?^=%&:/~\+#]*)?/g;
return text.match(regex);
}
Perché è sicuro: La rimozione dei quantificatori nidificati elimina il backtracking catastrofico. I quantificatori singoli come [a-zA-Z0-9_\-\.]+ vengono eseguiti in tempo lineare. Il pattern URL utilizza gruppi di non-cattura con un suffisso opzionale (?:...)? anziché ripetizioni nidificate, garantendo prestazioni prevedibili indipendentemente dalla lunghezza o dal contenuto dell'input.
Conclusione
Le prestazioni delle espressioni regolari rappresentano un problema di sicurezza, non solo di ottimizzazione. Rivedi tutti i pattern regex alla ricerca di quantificatori nidificati, classi di caratteri sovrapposte nei gruppi di ripetizione e alternative ambigue. Testa i pattern regex con input patologici (stringhe lunghe di caratteri validi seguiti da terminazioni non valide) per identificare il backtracking catastrofico prima del deployment. Quando possibile, sostituisci le regex complesse con funzioni di parsing delle stringhe che presentano caratteristiche di prestazioni prevedibili.

