Prompt di sicurezza: generici vs checklist misurabili (con esempi)
Perché chiedere all'IA di 'scrivere codice sicuro' non funziona. Una libreria di vincoli mirati per evitare SQL injection, segreti esposti e falle comuni.
«Scrivi il modulo di login in Python e fallo sicuro al 100%.» Se fai vibe coding, puoi aver scritto una frase del genere. L’IA risponde con entusiasmo. Tu ti fidi.
Il problema: chiedere codice «sicuro al 100%» è un’illusione. I modelli non hanno un concetto assoluto di sicurezza: seguono pattern. Se chiedi «sii sicuro», possono essere performativi — commenti rassicuranti, un hash di facciata — e lasciare falle logiche grosse.
Serve altro: vincoli misurabili. Regole che, leggendo il diff, o ci sono o non ci sono. Complementari al kickoff di progetto e utili prima di un modulo sensibile. Dopo, controlla col metodo dei 15 minuti di review.
| Generico | Utile? | Misurabile |
|---|---|---|
| «Niente credenziali in chiaro» Vago: dove le mette? | No | Leggi API key solo da os.environ / env. Mai nei sorgenti. Esempi: sk-ESEMPIO-NON-REALE. |
| «Proteggi il database» Da quale attacco? | No | Solo query parametrizzate. Vietate f-string / concatenazione per SQL con input utente. |
| «Non esporre il server a tutti» «Tutti» non è un bind | No | Bind di sviluppo su 127.0.0.1, mai 0.0.0.0 senza motivo. |
ℹ️ Nota / Prerequisito operativo
Nessun prompt certifica l’invulnerabilità. Alza la qualità dell’output e riduce le falle tipiche del codice IA. Restano test e review.
Perché i prompt vaghi illudono
I modelli conversazionali tendono ad accontentare. Con «API sicura, proteggi i dati», l’output può sembrare sicuro:
- nomi rassicuranti (
secure_password,safe_query); - commenti
# controllo di sicurezza; - cifratura dove non serve, dimenticando autorizzazioni sull’endpoint.
Senza una checklist «non fare X / fai sempre Y», c’è spazio all’interpretazione. I vincoli misurabili lo restringono.
Libreria di vincoli (copia-incolla)
Non incollare tutto in ogni prompt. Prendi solo i blocchi del modulo che stai per generare.
1. Segreti / env
VINCOLO SICUREZZA — SEGRETI:
Non inserire MAI API key, password, token o path personali assoluti nei sorgenti.
Leggi i segreti solo da variabili d'ambiente (es. os.environ) o da .env caricato a runtime.
Negli esempi usa sempre valori fittizi tipo sk-ESEMPIO-NON-REALE.
2. TLS / rete
VINCOLO SICUREZZA — RETE:
Nelle chiamate HTTP/HTTPS non impostare mai verify=False (né equivalenti tipo rejectUnauthorized: false).
Se serve un bypass temporaneo in dev, attivalo solo se una env dedicata (es. DEV_INSECURE_TLS=1) è impostata;
il default deve validare i certificati.
3. SQL parametrizzato
VINCOLO SICUREZZA — DATABASE:
Usa esclusivamente query parametrizzate.
Vietato comporre SQL con f-string, concatenazione + o .format() usando input utente.
4. Shell / subprocess
VINCOLO SICUREZZA — COMANDI DI SISTEMA:
Con subprocess (o equivalenti) non usare mai shell=True.
Passa eseguibile e argomenti come lista (es. ["ls", "-l", percorso]).
5. Validazione input
VINCOLO SICUREZZA — INPUT:
Ogni input esterno (form, query, JSON) va validato per tipo e limiti prima dell'uso.
Input non conforme → errore/400 (o eccezione). Non "aggiustare" in silenzio dati imprevisti.
6. Bind e CORS
VINCOLO SICUREZZA — BIND E CORS:
Server di sviluppo: bind solo su 127.0.0.1, non su 0.0.0.0 senza bisogno esplicito.
CORS: origini dichiarate; non usare Access-Control-Allow-Origin: * su API con dati autenticati.
(Approfondimento: CORS e asterisco.)
7. Cookie di sessione
VINCOLO SICUREZZA — COOKIE:
Cookie di sessione/auth: HttpOnly e Secure di default (non leggibili da JS; solo HTTPS).
(Dettaglio flag: cookie di sessione.)
Quando usarli
Il momento peggiore: app finita + «fai un audit di tutto». Contesto troppo ampio; possono apparire falsi positivi e saltare i veri buchi.
Il momento migliore: prima del modulo, o in una chat dedicata a quella funzione.
Esempio:
Scrivi una funzione FastAPI per cercare utenti per nome ed email.
[Incolla VINCOLO SQL]
[Incolla VINCOLO INPUT]
Niente UI. Un file. Aspetta conferma.
⚠️ Attenzione — Il contesto si diluisce
Nelle chat lunghe i vincoli iniziali possono sparire. Ripetili su ogni modulo critico o apri una chat nuova (come nel kickoff).
Laboratorio: generico vs misurabile
Nei miei test su un aggiornamento email utente:
Prompt generico: «Aggiorna l’email dell’utente, assicurati che sia sicuro.»
Esito tipico: SQL con f-string e un commento rassicurante. Pattern da falla tipica.
Con vincoli SQL + INPUT: query parametrizzate + validazione email prima del DB.
Non è magia: hai dato criteri che puoi vedere nel diff. Se falliscono, rispondi: «Hai violato il vincolo X. Riscrivi.» — non «rendilo più sicuro».
Domande Frequenti (FAQ)
Con questi prompt il codice è a prova di hacker?
No. Tolgono scorciatoie tipiche dell’IA (secret in chiaro, SQL concatenato). Non coprono da soli errori di autorizzazione (Utente B modifica dati di A).
Basta dire «segui OWASP»?
Troppo vago. Meglio come evitare la falla (query parametrizzate, no shell=True, …).
Devo mettere tutti i vincoli all’inizio?
No. Contestuali al modulo. Troppi insieme possono confondere il modello; il kickoff resta per le regole di sessione.
Come verifico se ha rispettato il vincolo?
È misurabile: chiave tra virgolette nei sorgenti? Fallito. f-string in SQL? Fallito. Poi Find in Files / i 15 minuti di review.
Funzionano anche in JS / altri linguaggi?
Sì. L’IA mappa i concetti (process.env, parametri PDO, ecc.). Adatta i nomi se vuoi essere ancora più esplicito.
Cosa faccio se ignora il vincolo?
Non Accept. Cita la regola violata e rifai il pezzo. Se capita spesso, spezza il task o riparti da kickoff.