modulo 08 / lezione 55
Pubblicare con responsabilità: sicurezza e progetto integrato
Segreti: API key, token, env, cosa non finisce mai in repo
Imparare a trattare segreti e configurazione come materiale sensibile, non come dettagli da sistemare alla fine.
Segreti: API key, token, env, cosa non finisce mai in repo
Un segreto in repo, anche per un commit, è compromesso. Non è opinione: è procedura standard di sicurezza. GitHub e bot scanner pubblici scansionano commit pubblici alla ricerca di chiavi API. Il tempo medio fra commit di una chiave AWS e suo abuso è minuti, non giorni.
Avvertenza importante: se un segreto è già finito in repo, NON limitarti a rimuoverlo dal prossimo commit. Devi RUOTARE (revocare e rigenerare) il segreto, perché la storia git contiene ancora la versione vecchia. Considerare quel segreto pubblico fino a rotazione.
Perché questa lezione conta
Modelli AI generano codice con process.env.STRIPE_SECRET_KEY ovunque, ma anche con chiavi hardcoded “per esempio”. Quei “per esempio” finiscono in produzione, in commit, in PR pubbliche. Conoscere la differenza fra variabili pubbliche, configurazione, segreti, credenziali — e cosa non deve mai uscire — è prerequisito di sicurezza, non opzionale.
Obiettivo operativo
Alla fine devi saper:
- distinguere variabili pubbliche, configurazione server, segreti, credenziali;
- usare correttamente
.env*,.gitignore, vault/pannelli hosting; - ruotare un segreto quando compromesso senza rompere produzione.
Nucleo della lezione
1. Categorie di valori sensibili (in ordine di rischio crescente)
Variabili pubbliche: visibili al client/utente. Per definizione, NON sono segreti.
Esempi: NEXT_PUBLIC_API_URL, VITE_PUBLIC_STRIPE_PUBLISHABLE_KEY, PUBLIC_GA_ID. Convenzione di prefisso (NEXT_PUBLIC_, VITE_PUBLIC_, PUBLIC_) che il framework rispetta esponendo nel bundle.
Va bene se finiscono nel bundle client. Niente dovrebbe essere “scoperto” se viste.
Configurazione server-side: usate solo dal server. Non sensibili in sé ma cambiano per ambiente.
Esempi: URL di servizi esterni, feature flags, dimensioni cache, level log. Vivono in .env server, non esposti al client.
Segreti: chiavi che permettono operazioni autorizzate per conto di te o tuoi utenti.
Esempi: STRIPE_SECRET_KEY, OPENAI_API_KEY, JWT_SIGNING_SECRET, DATABASE_URL con password, RESEND_API_KEY. Mai esposti, mai in repo.
Credenziali di servizio: accesso esteso a infrastruttura critica.
Esempi: AWS access keys, Google Cloud service account JSON, Stripe webhook signing secret. Spesso ruotabili solo manualmente, scope ampio. Tratta come dinamite.
Credenziali personali: SSH key, GitHub PAT, password personali. Mai in nessun progetto.
2. Dove vivono
.env (sviluppo): file locale. Gitignored. Contiene segreti per sviluppo. Spesso valori di test (Stripe in modalità test, account email di test).
.env.example (versionato): template di chiavi necessarie, senza valori reali. Indicativo.
Pannello hosting (produzione): Vercel, Netlify, Railway, Fly, AWS. Ogni piattaforma ha sezione “environment variables”. Lì vivono segreti reali, mai in repo.
Vault dedicato: per progetti più grandi o team. 1Password Secrets, Doppler, AWS Secrets Manager, Hashicorp Vault. Centralizzano segreti, ruotano automaticamente, audit log.
.gitignore deve sempre includere:
.env
.env.local
.env.*.local
*.pem
*.key
*.p12
*.cert
serviceaccount*.json
Verifica: dopo aver creato .env, git status non deve mostrarlo.
3. Procedure di sicurezza
Pre-commit hook anti-segreti: blocca commit con pattern sospetti. Strumenti: gitleaks, git-secrets, trufflehog. Setup richiede 10 minuti, salva incidenti.
Rotazione: quando un segreto viene compromesso (anche in repo privato, anche se pensavi nessuno l’avesse visto):
- Revoca subito il segreto vecchio nel pannello del provider.
- Genera nuovo segreto.
- Aggiorna in pannello hosting (produzione) e
.envlocale (sviluppo). - Verifica funzionamento.
- Audit log: cosa è successo, quando, cosa hai fatto. In caso di incidente futuro, traccia.
Separazione ambiente: chiavi sviluppo ≠ chiavi produzione. Mai usare chiave produzione in test. Errore = dati produzione cancellati.
Principle of least privilege: ogni chiave ha scope minimo necessario. API key di Stripe per webhook = scope webhook only. Service account GCP = solo bucket specifico, non intero progetto.
Audit periodico: ogni 3-6 mesi, lista chiavi attive, ruota quelle vecchie, revoca quelle non più usate.
Procedura pratica
Setup iniziale di un nuovo progetto:
.gitignore: include i pattern sopra prima di qualsiasi altro commit..env.example: crea con keys necessarie (vuoti)..env: crea local, popola con valori test/dev.- Verifica:
git statusnon vede.env. - Pre-commit hook (opzionale ma raccomandato):
gitleakso equivalente. - Pannello hosting: imposta env produzione.
- Documenta: in README cita quali variabili servono e dove ottenerle.
Mantenimento:
- ogni nuova dipendenza che richiede chiave → aggiungi a
.env.example; - mai committare valori reali, solo placeholder;
- ruotazione semestrale almeno per chiavi critiche.
Laboratorio guidato
Audit della tua repo principale:
Step 1: cerca pattern sospetti nel codice corrente.
git grep -E '(api[_-]?key|secret|password|token)\s*[=:]\s*["'\''][^"'\''$]+'
(filtra risultati: parole tipo apiKey: process.env.X sono ok; apiKey: "sk_live_..." sono compromessi).
Step 2: cerca nella storia git.
git log -p -- '**/*' | grep -iE 'sk_live_|api_key|password\s*=\s*["'\''][a-zA-Z0-9]{8,}'
Ogni hit nella storia = candidato a rotazione.
Step 3: verifica .gitignore. Tutti i pattern presenti?
Step 4: lista variabili in .env.example vs .env. Coincidenza? Se .env.example ha meno chiavi, manca documentazione. Se ha più, sono dichiarate ma non usate.
Step 5: pannello hosting. Tutte le chiavi necessarie sono lì? Sono i valori di produzione, non test?
Step 6: per ogni chiave attiva, identifica chi/cosa la usa. Quelle non usate da 6+ mesi → revoca.
Output atteso
Una procedura segreti per il progetto:
.gitignoreconfigurato;.env.exampleaggiornato;.envlocale popolato;- pannello hosting con valori produzione;
- pre-commit hook (consigliato);
- doc README sezione “Environment variables” con istruzioni per ottenere ogni chiave.
Studio passo passo
Studia questa lezione in tre passaggi, senza correre subito al prompt o al codice.
- Prima lettura: chiarisci l’obiettivo: imparare a trattare segreti e configurazione come materiale sensibile, non come dettagli da sistemare alla fine. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
- Seconda lettura: trasforma i contenuti in domande operative:
- Differenza tra variabili pubbliche, configurazione server-side, secret, token temporanei e credenziali di servizio.
- Uso di file .env, vault o pannelli hosting, con attenzione a commit, log, screenshot e build pubbliche.
- Procedure base: rotazione chiavi, revoca, separazione ambiente sviluppo/produzione, principle of least privilege.
- Applicazione: svolgi il laboratorio: revisionare una repo demo e trovare tutti i punti in cui un segreto potrebbe essere esposto. L’output da ottenere è: una checklist segreti con cosa controllare prima di push, deploy e condivisione del progetto.
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
- nessun segreto nel codice corrente;
- nessun segreto nella storia git (verificato);
.gitignoreblocca.env*;.env.exampledocumenta cosa serve;- pre-commit hook installato (opzionale ma consigliato);
- so come ruotare un segreto in 5 minuti;
- ho separato chiavi sviluppo da produzione.
Errori comuni
Segreto in commit “intanto, lo tolgo dopo”. Già compromesso. Storia git permanente.
Stesso .env per dev e prod. Test che cancella prod data: già successo.
Chiavi di test in produzione. Non funzionano per pagamenti reali, errori imbarazzanti.
Niente rotazione. Chiavi di 3 anni fa ancora attive, persone che hanno lasciato il team le hanno copiate.
Niente .env.example. Setup di nuovo dev richiede una settimana di chiarimenti.
Pre-commit hook ignorato. “Mai mi è successo” — finché non succede.
Segreti in screenshot/issue/Slack. Se rotti via canali condivisi, ruota. Sempre.
Prompt di lavoro
Audit segreti del mio progetto.
Ti incollo il contenuto di .env.example (no .env), .gitignore, e una lista delle dipendenze esterne che usano chiavi.
.env.example:
[contenuto]
.gitignore (sezioni rilevanti):
[contenuto]
Dipendenze con chiave:
- Stripe (pagamenti)
- Resend (email)
- Supabase (DB + auth)
- ...
Verifiche richieste:
1. Le chiavi in .env.example coprono tutte le dipendenze listate?
2. .gitignore blocca tutti i pattern di segreti?
3. Per ogni chiave, classifica: pubblica (può finire nel bundle client) / configurazione server / segreto / credenziale critica.
4. Per le segrete: scope tipico? rotazione consigliata?
5. Ci sono chiavi in .env.example con prefisso PUBLIC_/NEXT_PUBLIC_/VITE_PUBLIC_ che dovrebbero invece essere segrete?
Output: tabella chiave → categoria → dove vive → rischio → suggerimento.
Concludi con: 3 azioni prioritarie da fare subito.
Esercizio finale
Esegui il laboratorio sulla tua repo principale. Conta: chiavi sospette nel codice corrente? Chiavi mai entrate nella storia? Chiavi attive ma non usate? Tipicamente trovi almeno 1-2 problemi. Per ognuno, esegui rotazione + cleanup. Il progetto diventa più sicuro in 30-60 minuti, una volta sola.