Regola
Evita la ricorsione senza protezione
della profondità. La ricorsione senza
un'adeguata limitazione della profondità rischia il
stack overflow e crea vulnerabilità DoS
derivanti da input malesi. La ricorsione
con limiti di profondità
imposti è accettabile.
Lingue supportate: 45+Introduzione
Le funzioni ricorsive prive di limiti di profondità possono esaurire lo stack delle chiamate, provocando arresti anomali. Input malevoli, come oggetti JSON profondamente annidati o strutture dati cicliche, possono innescare intenzionalmente una ricorsione illimitata. Una singola richiesta manipolata può mandare in crash il servizio superando i limiti dello stack, creando una vulnerabilità di tipo denial-of-service estremamente facile da sfruttare.
Perché è importante
Implicazioni sulla sicurezza (attacchi DoS): gli attaccanti possono creare input in grado di innescare una ricorsione profonda, mandando in crash l'applicazione. Oggetti JSON o XML profondamente annidati o strutture dati collegate sono vettori di attacco comuni. Una singola richiesta malevisa esaurisce lo stack, bloccando l'intero servizio per tutti gli utenti.
Stabilità del sistema: gli errori di stack overflow causano l'arresto immediato del processo senza alcuna degradazione graduale. In produzione, questo si traduce in richieste scartate, transazioni interrotte e indisponibilità del servizio. Il ripristino richiede il riavvio dell'intera applicazione.
Esaurimento delle risorse: la ricorsione illimitata consuma memoria di stack in modo esponenziale. Ogni chiamata ricorsiva aggiunge un frame allo stack e catene di ricorsione profonda possono consumare megabyte di memoria. Ciò influisce sugli altri processi presenti sullo stesso server e può scatenare condizioni di out-of-memory.
Esempi di codice
❌ Non conforme:
function processNestedData(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const result = {};
for (const key in obj) {
result[key] = processNestedData(obj[key]);
}
return result;
}Perché è errato: L'assenza di un limite di profondità consente agli attaccanti di inviare oggetti profondamente annidati che superano i limiti dello stack. Input come {a: {a: {a: {...}}}} annidato a una profondità di 10.000 livelli fa crashare l'applicazione con un errore di stack overflow. La funzione esegue una ricorsione cieca senza verificarne la profondità.
✅ Conforme:
function processNestedData(obj, depth = 0, maxDepth = 100) {
if (depth > maxDepth) {
throw new Error('Maximum nesting depth exceeded');
}
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const result = {};
for (const key in obj) {
result[key] = processNestedData(obj[key], depth + 1, maxDepth);
}
return result;
}Perché questo è importante: Il parametro maxDepth il parametro limita la ricorsione a 100 livelli, prevenendo il sovraccarico dello stack. Questo limite è sufficientemente elevato per strutture dati annidate legittime (la maggior parte dei dati reali raramente supera i 10-20 livelli) e al tempo stesso abbastanza basso da bloccare gli attacchi prima che venga consumata una quantità significativa di memoria dello stack. Un input malevolo e profondamente annidato genera un errore anziché mandare in crash l'applicazione. Il controllo della profondità avviene prima dell'elaborazione, fallendo rapidamente quando i limiti vengono superati.
Conclusione
Aggiungi parametri di profondità a tutte le funzioni ricorsive che elaborano dati esterni. Imposta massimi di profondità ragionevoli in base alla complessità della struttura dati prevista. Lancia errori o restituisci valori predefiniti quando i limiti di profondità vengono superati, invece di causare un crash.

