
Indice dei contenuti
Una chiave API può sembrare una semplice stringa da incollare in un file. Finché funziona, è facile dimenticarsi che quella stringa potrebbe autorizzare chiamate a pagamento, accessi a dati o operazioni amministrative. 🔑 Ecco perché, quando sviluppo un’applicazione, cerco di considerare i segreti come una parte dell’architettura, non come un dettaglio da sistemare alla fine.
Non parlo soltanto di password: anche token OAuth, credenziali MariaDB, chiavi per servizi AI, webhook secret e certificati privati rientrano nella stessa famiglia. Il problema non è solo dove li conservi, ma anche chi può leggerli, per quanto tempo restano validi e come li revochi se finiscono nelle mani sbagliate.
Perché inserire le chiavi direttamente nel codice è una cattiva idea ⚠️
Immagina di scrivere $apiKey = '...'; in un file PHP e poi inviarlo a un repository Git. Anche se successivamente elimini la riga, il segreto può restare nella cronologia dei commit, nei fork, nei backup e nelle copie locali. Rendere privato il repository riduce l’esposizione, ma non risolve il problema alla radice.
Una regola utile è questa: il codice può essere distribuito, il segreto deve essere fornito all’applicazione attraverso un canale controllato. In pratica, separo la configurazione sensibile dalla logica applicativa e non pubblico mai file reali contenenti credenziali.
Variabili d’ambiente: utili, ma non magiche 🌱
Per molte applicazioni le variabili d’ambiente sono una soluzione pratica. Consentono di differenziare sviluppo, staging e produzione senza cambiare il codice. Tuttavia non sono una cassaforte: possono essere esposte da processi, strumenti diagnostici, dump o log configurati male.
In un progetto PHP, ad esempio, il valore può essere letto tramite getenv('APP_API_KEY'), purché il runtime lo riceva effettivamente. Eviterei di inserire il segreto nel comando lanciato a mano o in script condivisi, perché potrebbe finire nella cronologia della shell o nei log. Per ambienti più complessi preferisco un gestore dedicato dei segreti, con controllo degli accessi e rotazione.
Il file di configurazione non deve essere accessibile dal web 📁
In alcuni progetti PHP è naturale usare un file di configurazione. Il punto è evitare che sia servito come contenuto statico o leggibile da altri utenti del server. Se possibile, lo colloco fuori dalla document root e verifico proprietario, gruppo e permessi effettivi.
stat -c '%A %U:%G %a %n' /percorso/privato/config.phpIl permesso numerico corretto dipende dall’utente che esegue PHP e dal modello di isolamento dell’hosting. Applicare 600 senza controllare il proprietario può rendere il file illeggibile all’applicazione; lasciarlo leggibile a tutti, invece, aumenta il rischio. Meglio capire il processo prima di modificare i permessi.
Su un server con più siti, la separazione è ancora più importante: se applicazioni diverse condividono lo stesso utente di sistema, un problema su un progetto può esporre anche i segreti degli altri. Ho approfondito questo aspetto nella guida all’hardening di una VPS Linux.
Un file .env va trattato come una credenziale, non come documentazione
È normale avere un file .env.example con nomi di variabili e valori fittizi. Il file .env reale, invece, dovrebbe essere escluso dal versionamento, protetto sul filesystem e non raggiungibile via HTTP. Inserirlo in .gitignore aiuta soltanto se non è già stato tracciato: se è entrato nella storia di Git, occorre considerare le credenziali potenzialmente compromesse.
Attenzione anche ai log. Stampare l’intera configurazione durante il debugging può sembrare comodo, ma rischia di registrare token che poi finiscono nei sistemi di monitoraggio o nelle segnalazioni di errore.
Il principio del privilegio minimo vale anche per le API 🛡️
Una chiave che può leggere soltanto alcuni dati è meno pericolosa di una chiave con privilegi amministrativi completi. Quando un servizio lo permette, creo credenziali distinte per ambiente e funzione: una per lo sviluppo, una per la produzione, eventualmente una per le operazioni in sola lettura.
Lo stesso criterio vale per MariaDB: l’utente usato dal sito non dovrebbe possedere privilegi globali che non gli servono. Se una chiave viene compromessa, ridurre il suo raggio d’azione può fare una differenza enorme.
Cosa fare se una chiave è finita online? 🚨
- Revocarla o ruotarla immediatamente dal pannello del provider: cancellarla dal file non basta.
- Verificare i log di utilizzo e le eventuali operazioni anomale.
- Creare una nuova credenziale con privilegi minimi.
- Aggiornare in sicurezza tutti i servizi che dipendono dalla vecchia chiave.
- Rimuovere il segreto dai punti di esposizione e valutare la bonifica della cronologia Git, senza considerarla un’alternativa alla revoca.
La checklist che userei prima di andare online ✅
- Nessun segreto hardcoded nel repository.
- Credenziali diverse tra sviluppo e produzione.
- File sensibili protetti e non accessibili dal browser.
- Permessi API e database limitati allo stretto necessario.
- Log e messaggi di errore privi di token e password.
- Procedura documentata per revoca e rotazione.
- Backup protetti, perché possono contenere gli stessi segreti della produzione.
Quando lavori con automazioni e coding agent, questo controllo diventa ancora più importante: non serve concedere a un agente tutte le chiavi di produzione per fargli modificare un componente. Ne parlo anche nell’articolo sugli agenti AI e i permessi eccessivi.
Per approfondire il ciclo di vita delle credenziali, dalla creazione alla revoca, consiglio la Secrets Management Cheat Sheet di OWASP. La lezione che mi porto a casa è semplice: una chiave sicura non è quella nascosta meglio, ma quella che puoi controllare, limitare e disattivare rapidamente. 🔐
