modulo 08 / lezione 59

Pubblicare con responsabilità: sicurezza e progetto integrato

OWASP top hits per app generate: injection, XSS, auth rotta

Conoscere le famiglie di vulnerabilità più probabili nei prototipi AI e i controlli minimi per cercarle.

75 min Vibe Coding

OWASP top hits per app generate: injection, XSS, auth rotta

OWASP Top 10 è la lista di vulnerabilità web più comuni. Per il vibe coder, conoscerla è prerequisito di pubblicabilità. Cinque famiglie coprono il 90% dei rischi nei prototipi AI: injection, XSS, broken access control, broken auth, dipendenze vulnerabili. Conoscerle a memoria e sapere come testare è skill di base.

Perché questa lezione conta

Modelli AI producono codice plausibile e spesso vulnerabile. Pattern come “concatena variabile in query SQL”, “innerHTML dell’input utente”, “verifica ruolo dal token senza validarlo” sono frequenti. Riconoscerli prima del merge è prevenzione attiva. Senza, ogni prototipo pubblicato è esposizione.

Obiettivo operativo

Alla fine devi saper:

  1. nominare le 5 famiglie e riconoscerne sintomi nel codice;
  2. testare presenza/assenza di vulnerabilità con tecniche manuali base;
  3. costruire una checklist sicurezza per il prossimo deploy.

Nucleo della lezione

1. Injection

SQL injection: input utente concatenato in query. Esempio cattivo: "SELECT * FROM users WHERE email = '" + email + "'". Utente manda ' OR 1=1 -- → bypass.

Mitigazione: query parametrizzate / prepared statements. SEMPRE.

// MALE
const query = `SELECT * FROM users WHERE email = '${email}'`

// BENE
const query = 'SELECT * FROM users WHERE email = $1'
const result = await db.query(query, [email])

ORM moderni (Drizzle, Prisma, TypeORM) parametrizzano automaticamente. Evita raw SQL su input.

NoSQL injection: simile ma per Mongo, ecc. db.find({ email: req.body.email }) con body {email: {$ne: null}} → bypass. Validazione strict del tipo.

Command injection: exec("ls " + req.query.dir). Mai concatenare input in shell. Usa lib safe (child_process.execFile con array di args).

Prompt injection (per app AI): user input concatenato in system prompt → utente sovrascrive istruzioni. Pattern: usa structured input (variabili dedicate), separa user content da istruzioni.

2. XSS (Cross-Site Scripting)

Stored XSS: utente invia <script> nel commento, server salva, altri utenti lo vedono → script eseguito nel loro browser.

Reflected XSS: parametro URL incluso nella response senza escape. ?q=<script>... → script eseguito.

DOM-based: JS lato client legge URL/storage e scrive in DOM senza escape.

Mitigazione:

  • Encoding output: testo dell’utente reso come testo, non come HTML. Frameworks moderni (React, Vue, Svelte) fanno encoding automatico in {variable}. NON {innerHTML} / {rawHtml}.
  • Content Security Policy (CSP): header che limita cosa può eseguirsi. script-src 'self' blocca inline e third-party.
  • Sanitizer per HTML user-generated: se accetti rich text, usa libreria (DOMPurify) per pulire prima del render. Mai roll your own.
  • HttpOnly cookies: token non accessibili da JS. Mitiga ma non risolve XSS.

Test: prova a inserire <script>alert(1)</script> nei campi user-input. Se appare il popup, XSS. Se appare come testo letterale, ok.

3. Broken Access Control

Dalla lezione 55: ogni controllo deve essere lato server. Tipici:

  • IDOR: /api/orders/:id non verifica ownership.
  • Privilege escalation: endpoint admin accessibile a non-admin (URL nascosto solo nell’UI).
  • Mass assignment: campi sensibili modificabili da client.
  • Forced browsing: file/risorse accessibili tramite URL prevedibile (/uploads/files/123).

Test: con utente A loggato, prova URL/azione che dovrebbero essere di utente B o admin. Se passa, vulnerabile.

4. Broken Authentication

Errori comuni:

  • Password deboli accettate: niente requisito di minimum length/complessità.
  • Niente rate limiting: brute force possibile. Login API senza throttling.
  • Session fixation: attaccante imposta session ID prima del login, lo riusa dopo.
  • Sessioni eterne: niente scadenza. Token rubato = account compromesso a vita.
  • Logout incompleto: cookie cleared dal client, sessione server attiva. Token ancora valido.
  • Reset password debole: token prevedibile, scadenza assente, non monouso.

Mitigazione:

  • password requirements: minimum 8 caratteri, password manager-friendly (no requisiti arbitrari);
  • rate limiting su /login (es. 5 tentativi falliti → blocco 15 min);
  • session tokens crittograficamente sicuri (non incremental id);
  • scadenza sessioni (idle timeout + absolute timeout);
  • logout invalida sessione lato server;
  • token reset password: random sufficiente, scadenza 15-60 min, monouso.

5. Dipendenze vulnerabili

Codice generato include librerie. Librerie hanno CVE.

Mitigazione:

  • npm audit / pnpm audit / yarn audit regolare;
  • Dependabot o Renovate per PR automatiche su update di sicurezza;
  • aggiornamento patch version frequente (low risk);
  • audit profondo prima di major version update;
  • minimizzare dipendenze (vedi lezione 44).

6. Configurazioni insicure

Codice generato spesso include config “for development”:

  • CORS permissivo (Access-Control-Allow-Origin: *);
  • Debug abilitato (DEBUG=*, stack trace esposti);
  • HTTPS opzionale, HTTP fallback;
  • security headers mancanti (HSTS, CSP, X-Frame-Options);
  • error messages dettagliati (Error: PostgreSQL connection refused at 192.168.1.5:5432).

Mitigazione: prima del deploy, security headers (helmet middleware, framework defaults), HTTPS forzato, debug disabled, error message generici per esterno (log dettagliati internamente).

Procedura pratica

Prima del deploy pubblico:

  1. Audit dipendenze: npm audit. Risolvi alto/critico.
  2. Test injection: input ostili nei campi principali. Verifica encoding.
  3. Test access control: utente A prova azioni di B. Devi ricevere 403/404.
  4. Test auth: brute force semi-automatico (script di 100 tentativi), verifica rate limit.
  5. Headers: securityheaders.com o equivalent verifica HSTS, CSP, etc.
  6. Config: debug off, HTTPS forced, errori generici per esterno.
  7. Logging: monitoring di errori sensibili (login falliti, 403 ripetuti).

Laboratorio guidato

Mini-pentest manuale di una piccola app:

1. Injection: in ogni form/parametro URL, prova:

  • '; DROP TABLE users; --
  • <script>alert(1)</script>
  • {$ne: null} (per NoSQL)
  • ../../etc/passwd (path traversal)

Per ognuno: l’app risponde correttamente (input come dato) o fa qualcosa di anomalo?

2. Access control: con account utente A, prova a:

  • accedere a risorsa di B via cambio id in URL;
  • chiamare endpoint admin direttamente;
  • modificare ruolo nel body request;
  • accedere a file in /uploads/ di altri utenti.

3. Auth: tenta:

  • 100 login con password sbagliate dallo stesso IP. Rate limit?
  • richiesta reset password con email casuale. Cosa risponde? (Errore distintivo = enumeration).
  • token reset usato due volte. Funziona la seconda?
  • logout, poi richiesta API con cookie vecchio. Funziona?

4. Dipendenze: npm audit. Critico/alto presente?

5. Config: apri DevTools, verifica:

  • Strict-Transport-Security header presente?
  • Content-Security-Policy configurata?
  • errori 500 mostrano stack trace?

Per ogni vulnerabilità trovata: priorità + fix + test di regressione.

Output atteso

Una checklist OWASP minima per il tuo progetto + risultati del pentest manuale + lista fix prioritari.

Studio passo passo

Studia questa lezione in tre passaggi, senza correre subito al prompt o al codice.

  1. Prima lettura: chiarisci l’obiettivo: conoscere le famiglie di vulnerabilità più probabili nei prototipi AI e i controlli minimi per cercarle. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
  2. Seconda lettura: trasforma i contenuti in domande operative:
  • Injection e query non parametrizzate, XSS da HTML non sanificato, CSRF dove rilevante, auth e sessioni mal gestite.
  • Access control rotto: utenti che leggono o modificano risorse non proprie.
  • Dipendenze vulnerabili e configurazioni insicure generate per comodità.
  1. Applicazione: svolgi il laboratorio: passare una piccola app attraverso una checklist OWASP semplificata e segnare rischi concreti. L’output da ottenere è: una lista di controlli sicurezza da eseguire prima di mostrare un prototipo a utenti reali.

Prima di passare alla lezione successiva, controlla di avere un artefatto concreto: una tabella, un prompt, una checklist, un mini report, un diff commentato o una decisione scritta. Nel vibe coding la comprensione resta astratta finché non produce una traccia verificabile.

Checklist di verifica

  • conosco le 5 famiglie OWASP più comuni;
  • ho testato manualmente almeno 3 famiglie sul mio progetto;
  • npm audit non ha critici/alti;
  • security headers configurati;
  • rate limiting su login;
  • error messages generici per esterno.

Errori comuni

“Sono solo prototipo, sicurezza dopo”. Prototipo va in produzione, sicurezza non viene mai. Almeno minimo OWASP da subito.

Affidare sicurezza all’AI. Modello propone soluzioni plausibili, non sempre corrette. Verifica.

Niente HTTPS. Senza, ogni misura auth è teatro.

Errori di produzione con stack trace. Leak di info interni: stack DB, path file, versioni librerie.

CORS *. “Funziona da ogni dominio”. Anche da attaccanti.

Cookie senza HttpOnly/Secure. XSS leak token, http leak in chiaro.

Niente rate limiting. Brute force diventa banale.

Aggiornamenti dipendenze ignorati. CVE noti aperti.

Prompt di lavoro

Audit sicurezza per la mia app: [descrizione]

Stack: [...]
Endpoint principali: [lista]
Auth scheme: [...]

Per ognuna delle 5 famiglie OWASP più comuni:

1. Injection (SQL/NoSQL/Command/Prompt): pattern nel codice da cercare, test manuale.
2. XSS: dove può manifestarsi, test manuale, encoding strategy.
3. Broken access control: matrice ruoli × azioni, test IDOR e privilege escalation.
4. Broken auth: rate limiting, sessione, reset password, logout.
5. Dipendenze e config: audit dipendenze, security headers, debug off.

Per ognuna:
- pattern specifici nel mio stack da verificare
- 3-5 test manuali concreti (input/azione + cosa cercare)
- mitigazione concreta

Output: lista prioritizzata di azioni per il prossimo deploy. Non scrivere codice; voglio prima decidere priorità.

Esercizio finale

Esegui pentest manuale su tuo progetto come da laboratorio. Tipicamente trovi 2-4 vulnerabilità. Per ognuna: priorità, fix, test. Anche un’ora di pentest manuale produce risultati significativi su prototipi AI; vulnerabilità rare in prototipi maturi sono comuni in quelli generati senza scan.