La validazione dell'input è il processo di verifica che i dati in ingresso rispettino il formato, il tipo e l'intervallo di valori attesi prima che l'applicazione li elabori. Secondo l'OWASP Input Validation Cheat Sheet (2025), l'assenza di validazione è la causa principale della maggior parte delle vulnerabilità critiche. Controllare i dati in ingresso è la prima linea di difesa, che impedisce a dati non validi o dannosi di entrare nel sistema.
Punti chiave
La validazione dell'input è la verifica che i dati che arrivano all'applicazione da un utente, da un servizio esterno o da un altro componente rispettino i criteri attesi. Questi criteri includono il tipo di dati (stringa, numero, data), il formato (email, URL, telefono), l'intervallo di valori (età da 18 a 120), la lunghezza (password da 8 a 128 caratteri) e i caratteri consentiti (solo lettere latine, cifre, trattino). Senza validazione, l'applicazione può elaborare dati che causano errori di esecuzione, corruzione dei dati o vulnerabilità di sicurezza.
L'assenza di validazione dell'input è la causa principale di vulnerabilità come SQL Injection, XSS, Command Injection, Path Traversal e Buffer Overflow. Secondo MITRE CWE (2025), CWE-20 (Improper Input Validation) occupa il secondo posto nella classifica degli errori software più pericolosi. La validazione è la prima linea di difesa nel modello di sicurezza Defense in Depth: taglia i dati non validi prima che raggiungano gli altri componenti del sistema.
La validazione rifiuta i dati che non rispettano i criteri. La sanitizzazione (pulizia) modifica i dati rimuovendo o sfuggendo le parti pericolose. Ad esempio, quando si inserisce contenuto HTML, la validazione può controllare la lunghezza del testo e la sanitizzazione rimuovere i tag script tramite la libreria HTML Purifier o DOMPurify. La sanitizzazione non sostituisce la validazione: lavorano in coppia. La validazione è una politica "consentito/vietato", mentre la sanitizzazione è "pulito prima dell'uso".
La validazione è classificata in base alla profondità del controllo. La validazione di formato è la più semplice e veloce, mentre la validazione di business è la più complessa e dipendente dal contesto. Tutti e tre i livelli devono essere applicati in sequenza: prima il formato, poi la semantica, poi la logica di business. Saltare un livello può causare un funzionamento errato del sistema o vulnerabilità.
| Livello | Cosa controlla | Esempio |
|---|---|---|
| Formato | Tipo di dati, lunghezza, espressione regolare | L'email contiene @, lunghezza 5-100 |
| Semantica | Correttezza logica del valore | La data di nascita non è nel futuro |
| Validazione di business | Conformità alle regole di business | L'importo del bonifico non supera il saldo |
Controllo del tipo di dati, della dimensione, del formato e dei caratteri consentiti. Viene implementata tramite espressioni regolari, tipi integrati dei linguaggi e librerie di validazione. Esempi: controllo di un UUID (formato 8-4-4-4-12 cifre esadecimali), controllo di un numero di telefono (solo cifre, + all'inizio, da 7 a 15 caratteri), controllo di un intero (valore nell'intervallo Integer.MIN_VALUE — Integer.MAX_VALUE). La validazione di formato è il livello minimo richiesto per qualsiasi campo di input.
Controllo della correttezza logica dei dati nel contesto del dominio. Ad esempio: la data di inizio non è successiva alla data di fine, l'età rientra in limiti ragionevoli per il sistema, le coordinate sono all'interno dell'area di servizio. La validazione semantica richiede la comprensione del contesto di business e non può essere eseguita solo in base al formato. Esempio: il campo "numero di biglietti" può superare la validazione di formato (intero, > 0), ma semanticamente non può superare il numero di posti disponibili.
Il livello più complesso — verifica della conformità dei dati alle regole di business dell'applicazione. Esempi: un utente non può eliminare l'unico amministratore, l'importo dell'ordine non supera il limite di credito, un prodotto può essere ordinato solo se è disponibile. La validazione di business richiede spesso query al database o servizi esterni e viene eseguita dopo i controlli di formato e semantica. Gli errori di validazione di business sono la causa più frequente di insoddisfazione degli utenti.
La validazione lato client (nel browser o nell'app mobile) serve per la comodità dell'utente: feedback immediato senza inviare dati al server. Tuttavia, la validazione lato server è l'unica affidabile, perché il codice client può essere sempre aggirato. Invia richieste tramite gli strumenti di sviluppo, Postman o un proxy (Burp Suite) — e la validazione lato client cessa di esistere. Secondo PortSwigger Research (2025), più del 90% delle applicazioni web testate fa affidamento esclusivamente sulla validazione lato client per almeno un campo.
La validazione lato client può disattivare il pulsante di invio, evidenziare gli errori e mostrare suggerimenti. La validazione lato server è un controllo obbligatorio di ogni parametro, anche se il client lo ha già controllato. Duplicare la validazione su entrambi i livelli è una pratica standard. Il server deve verificare i dati come se il client non esistesse. Questo garantisce protezione da richieste modificate, attacchi automatizzati e client dannosi.
Nel web — attributi HTML5 (required, pattern, min/max, type="email") e JavaScript. Nelle app mobili — validatori nativi dei campi di testo (InputFilter su Android, textField(:shouldChangeCharactersIn:) su iOS). React Hook Form e Formik per React, Vuelidate per Vue, Angular Reactive Forms — librerie popolari per la validazione lato client. Tutte supportano regole personalizzate e validazione asincrona (controllo dell'unicità del login sul server).
// Esempio di validazione lato server con Express e Joi
const Joi = require('joi');
const userSchema = Joi.object({
email: Joi.string()
.email()
.required()
.max(255),
age: Joi.number()
.integer()
.min(18)
.max(120)
.required(),
password: Joi.string()
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,128}$/)
.required()
});
app.post('/api/users', async (req, res) => {
const { error, value } = userSchema.validate(req.body);
if (error) {
return res.status(400).json({
error: error.details[0].message
});
}
// value — dati già validati e sicuri
const user = await User.create(value);
res.status(201).json(user);
});
Le app mobili impongono requisiti particolari alla validazione dei dati. Lo schermo è più piccolo — gli errori devono essere concisi, la tastiera contestuale (numerica per inserire numeri) e il controllo asincrono per non bloccare l'interfaccia. Le piattaforme native forniscono meccanismi di validazione integrati che dovrebbero essere usati per impostazione predefinita. Le Material Design Guidelines per Android e le Human Interface Guidelines per iOS contengono raccomandazioni dettagliate per visualizzare gli errori di validazione.
Jetpack Compose offre un approccio dichiarativo alla validazione tramite la gestione dello stato. Ogni campo di input è legato a uno stato (MutableState) e l'errore viene calcolato in base al valore corrente. La libreria Compose Validator semplifica la creazione di regole: required, email, min/max length, pattern. La validazione viene attivata al cambio del testo (onValueChange) o al tentativo di invio del modulo. Si consiglia di mostrare l'errore solo dopo il primo invio o dopo che l'utente ha finito di digitare (debounce 300-500ms).
SwiftUI non ha un meccanismo integrato di validazione dei moduli, ma permette di implementarlo facilmente tramite Combine e property wrapper. Usa @State per il valore del campo e una proprietà calcolata per l'errore. Il framework ValidatedPropertyKit fornisce decoratori pronti: @Validated().email(), @Validated().range(18...120). Raccomandazione iOS — usare i tipi di tastiera (UIKeyboardType.emailAddress, .numberPad) e la capitalizzazione automatica per ridurre il numero di errori a livello di input.
Flutter fornisce le classi Form e TextFormField con validazione integrata tramite un callback di validatore. Ogni campo restituisce un errore come stringa o null se i dati sono corretti. FormState.validate() esegue il controllo di tutti i campi del modulo. Il pacchetto reactive_forms per i casi complessi: validatori personalizzati, controllo asincrono, regole dinamiche. Flutter Web e la versione mobile usano la stessa API, semplificando la manutenzione.
// Esempio di validazione di un modulo in Flutter
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value)) {
return 'Enter a valid email';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Elabora dati validi
}
},
child: Text('Invia'),
),
],
),
)
I framework moderni forniscono validatori integrati che coprono l'80% delle esigenze. Il restante 20% richiede regole personalizzate, espressioni regolari o la composizione di quelle esistenti. Il principio chiave è che la validazione deve essere dichiarativa per essere facilmente letta, testata e mantenuta. Evita la logica di validazione sparsa tra controller e schermate — spostala in classi o schemi separati.
| Strumento | Piattaforma | Caratteristiche |
|---|---|---|
| Joi | Node.js | Schemi dichiarativi, messaggi personalizzati |
| Pydantic | Python | Type hints, validazione automatica del modello |
| Zod | TypeScript | Inferenza dei tipi, tipizzazione rigorosa |
| javax.validation | Java | Bean Validation, @NotNull, @Size, @Pattern |
| FluentValidation | .NET | API fluente, rulesets, regole condizionali |
White-list (lista bianca) — definisci quali dati sono consentiti; tutto il resto viene rifiutato. Black-list (lista nera) — definisci quali dati sono vietati; tutto il resto viene accettato. La lista bianca è sempre più affidabile: sai esattamente quali dati passeranno. La lista nera richiede di prevedere tutti i possibili attacchi, il che è impossibile. Esempio: nel controllo dell'età, usa una lista bianca (solo numeri da 18 a 120) piuttosto che una lista nera (vietare "0", "-1", "999999").
Le espressioni regolari sono uno strumento efficace per la validazione di formato, ma possono essere fonte di attacchi ReDoS (Regular Expression Denial of Service). Alcuni pattern (ad esempio, (a+)+b) causano un backtracking catastrofico su stringhe lunghe, caricando completamente la CPU del server. Usa librerie regex comprovate e limita la lunghezza della stringa prima di applicare un'espressione regolare. Per i casi complessi (email, URL), usa i parser integrati dei linguaggi piuttosto che regex fatti in casa.
Anche gli sviluppatori esperti commettono errori nell'implementare la validazione. I più frequenti: validazione solo sul client, regole troppo rigide (password "Must contain uppercase, lowercase, digit, special char, >= 12 chars, must not repeat characters"), messaggi di errore poco informativi ("Error: invalid input") e ignorare i casi limite (spazi all'inizio/fine, caratteri Unicode, stringhe vuote). Ciascuno di questi errori peggiora l'UX e può ridurre la conversione dei moduli.
if (value) non distingue una stringa vuota da zero, false o "0"La migliore pratica è un sistema centralizzato di validazione coperto da test unitari. Ogni regola dovrebbe essere testata separatamente: valori limite, dati corretti, attacchi tipici (tentativi di SQLi, payload XSS, stringhe molto lunghe). I test di regressione sulla validazione impediscono l'indebolimento accidentale delle regole durante il refactoring. Usa i test basati sulle proprietà (QuickCheck, fast-check) per generare dati casuali e verificare che la validazione non fallisca con un'eccezione.
Domande frequenti
La validazione rifiuta i dati non validi, mentre la sanitizzazione li pulisce. Ad esempio, quando si inserisce testo HTML, la validazione controlla la lunghezza massima e la sanitizzazione rimuove i tag script tramite DOMPurify. Entrambi i processi sono obbligatori: la validazione per il controllo del formato, la sanitizzazione per la sicurezza dell'output.
No, mai. La validazione lato client viene aggirata facilmente tramite intercettazione e modifica delle richieste. Usa strumenti come Burp Suite o semplicemente curl. La validazione lato server è l'unico modo affidabile per proteggere il sistema. La validazione lato client serve solo a migliorare l'esperienza utente.
Controlla il tipo MIME (non solo l'estensione), la dimensione del file e la firma (byte magici all'inizio del file) tramite la validazione della firma del file. Non fidarti mai dell'estensione — rinomina il file al salvataggio. Per le immagini, ri-encodale con una libreria server (ImageMagick, Sharp), che rimuove il codice incorporato dai dati EXIF.
ReDoS (Regular Expression Denial of Service) è un attacco in cui un aggressore invia una stringa appositamente costruita che provoca un backtracking catastrofico in un'espressione regolare. Di conseguenza, la CPU del server viene caricata al 100% e non viene prodotta alcuna risposta. Protezione: limitare la lunghezza della stringa, timeout per le regex e uso di pattern comprovati.
Sì, se i dati vengono visualizzati in una WebView o usati in un contesto HTML. Se il backend viene compromesso, i dati possono contenere codice dannoso. Valida e sanifica tutti i dati visualizzati all'utente, indipendentemente dalla fonte. Nelle app mobili, questo è particolarmente importante per i componenti ibridi.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche