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.

75 min Vibe Coding

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:

  1. distinguere variabili pubbliche, configurazione server, segreti, credenziali;
  2. usare correttamente .env*, .gitignore, vault/pannelli hosting;
  3. 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):

  1. Revoca subito il segreto vecchio nel pannello del provider.
  2. Genera nuovo segreto.
  3. Aggiorna in pannello hosting (produzione) e .env locale (sviluppo).
  4. Verifica funzionamento.
  5. 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:

  1. .gitignore: include i pattern sopra prima di qualsiasi altro commit.
  2. .env.example: crea con keys necessarie (vuoti).
  3. .env: crea local, popola con valori test/dev.
  4. Verifica: git status non vede .env.
  5. Pre-commit hook (opzionale ma raccomandato): gitleaks o equivalente.
  6. Pannello hosting: imposta env produzione.
  7. 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:

  • .gitignore configurato;
  • .env.example aggiornato;
  • .env locale 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.

  1. 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.
  2. 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.
  1. 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);
  • .gitignore blocca .env*;
  • .env.example documenta 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.