Pipeline CI/CD sicura: dipendenze, segreti e permessi sotto controllo

Una pipeline CI/CD trasferisce codice verso ambienti reali usando identità, dipendenze e credenziali. La stessa automazione che accelera il rilascio può quindi amplificare un errore o un attacco: un passaggio compromesso può modificare l’artefatto, leggere segreti o distribuire software in produzione.
Una pipeline CI/CD sicura non dipende da un singolo scanner. Usa controlli stratificati: input affidabili, permessi minimi, segreti temporanei, build riproducibili, artefatti verificati, approvazioni e tracce consultabili.
Il modello di rischio: la pipeline è una supply chain
La pipeline collega repository, runner, azioni di terze parti, package manager, registry, cloud e ambienti. OWASP include tra i rischi principali il controllo insufficiente dei flussi, la gestione debole di identità e accessi, l’abuso della catena delle dipendenze, la pipeline avvelenata, credenziali esposte, artefatti non verificati e logging insufficiente.
Il primo passo è disegnare il flusso reale: chi può modificare workflow e codice, cosa parte automaticamente, quali sistemi vengono contattati, quali credenziali entrano in ogni job e quale output raggiunge produzione.
1. Separare gli eventi per livello di fiducia
Un push su un branch protetto, una pull request interna e una richiesta proveniente da un fork non hanno lo stesso livello di fiducia. I contenuti non fidati non dovrebbero essere eseguiti in un contesto con segreti o permessi di scrittura.
Le pipeline devono distinguere build e test da rilascio. Il job di verifica può lavorare con privilegi ridotti; la distribuzione richiede condizioni aggiuntive: branch o tag ammesso, controlli superati, ambiente autorizzato e, quando opportuno, approvazione.
2. Proteggere workflow e branch
I file della pipeline sono codice con capacità operativa. Devono essere sottoposti a review, regole di branch e proprietari espliciti. Una modifica a permessi, runner, comandi di deploy o provenienza delle azioni merita una revisione più rigorosa di un cambiamento ordinario.
È utile applicare CODEOWNERS o meccanismi equivalenti alle directory dei workflow, impedire push diretti sui branch di rilascio e richiedere controlli prima del merge. Gli amministratori non dovrebbero aggirare abitualmente le stesse regole.
3. Rendere immutabili azioni e dipendenze
GitHub raccomanda di fissare le azioni di terze parti a uno SHA completo, perché è il modo per riferirsi a una revisione immutabile. Un tag è più leggibile, ma può cambiare. Lo SHA va verificato nel repository corretto e aggiornato attraverso un processo controllato.
Lo stesso principio vale per le dipendenze applicative: lockfile versionato, installazione deterministica, registry espliciti e controllo degli aggiornamenti. La scansione delle vulnerabilità note è utile, ma non impedisce da sola dependency confusion, pacchetti malevoli o script di installazione pericolosi.
4. Ridurre i permessi del token di pipeline
Ogni job dovrebbe ricevere solo i permessi necessari e per il tempo necessario. Se un test deve leggere il repository, non dovrebbe poter creare release o modificare issue. Il deploy in staging non dovrebbe avere automaticamente accesso alla produzione.
I permessi vanno dichiarati esplicitamente, evitando default troppo ampi. Ambienti differenti devono usare ruoli e credenziali differenti. Per operazioni sensibili è utile separare chi può modificare il workflow da chi può approvare il rilascio.
5. Sostituire segreti permanenti con identità temporanee
Le chiavi cloud a lunga durata aumentano esposizione e costi di rotazione. Quando il provider lo supporta, OpenID Connect consente alla pipeline di ottenere credenziali temporanee sulla base di repository, branch, ambiente e altre condizioni verificabili.
I segreti ancora necessari devono risiedere in un vault o nel sistema protetto della piattaforma, non nel repository, nelle immagini o nei file di configurazione. Mascherare il valore nei log aiuta, ma non risolve comandi che lo trasformano, lo copiano in artefatti o lo inviano a servizi esterni.
6. Eseguire secret scanning prima e durante la build
Il controllo deve iniziare sul commit e continuare sugli output. Un segreto può entrare nel codice sorgente, in un file generato, in una variabile stampata, in una cache o in un’immagine container. Quando viene rilevato, va considerato compromesso: rimuoverlo dal repository non basta, occorre revocarlo e sostituirlo.
La risposta dovrebbe essere documentata con proprietario, tempo di revoca, causa e controllo preventivo aggiunto. Le eccezioni dello scanner devono avere scadenza e motivazione.
7. Isolare runner e build
I runner condivisi o persistenti possono conservare file, credenziali o processi. Per attività ad alto rischio è preferibile un ambiente effimero, distrutto al termine del job, con rete e filesystem limitati. Gli output da conservare devono essere selezionati esplicitamente.
Le build non dovrebbero avere accesso indiscriminato a Internet. Dove possibile, usare proxy, mirror o allowlist riduce il rischio di scaricare dipendenze inattese o esfiltrare dati. Anche cache e artefatti intermedi devono avere chiavi, retention e visibilità coerenti.
8. Firmare e verificare gli artefatti
Una pipeline sicura deve sapere che cosa sta distribuendo e chi lo ha prodotto. Hash, firma e attestazione collegano l’artefatto al processo di build. Il framework SLSA usa la provenance per descrivere builder, processo e input; la protezione diventa effettiva quando la provenance viene verificata rispetto ad aspettative predefinite.
La fase di deploy dovrebbe rifiutare un pacchetto modificato, proveniente da un workflow o repository non autorizzato, oppure privo dell’attestazione richiesta. Ricostruire in produzione da sorgenti diversi dall’artefatto testato rompe questa catena di fiducia.
9. Usare ambienti e approvazioni come cancelli
Gli ambienti di deployment possono imporre branch consentiti, revisori, ritardi o regole personalizzate. L’approvazione manuale non deve sostituire i test: è utile per cambiamenti ad alto impatto, migrazioni, finestre concordate e verifica dell’evidenza prodotta dalla pipeline.
Il revisore dovrebbe vedere versione, commit, controlli superati, differenze, artefatto e piano di rollback. Un pulsante senza contesto crea soltanto una firma formale.
10. Registrare eventi e preparare il rollback
Per ogni rilascio servono identità, commit, workflow, artefatto, ambiente, approvatore e risultato. I log di sicurezza devono avere retention adeguata e accesso separato dalla pipeline che controllano, così un attaccante non può cancellare facilmente le tracce.
Il rollback va provato. Deve indicare quale artefatto precedente è verificato, come si gestiscono migrazioni di dati e chi prende la decisione. “Rieseguire l’ultima pipeline” non è un piano se la causa dell’incidente è nella pipeline stessa.
Pipeline minima in quattro cancelli
- Source gate: branch protetto, review del workflow, dipendenze fissate.
- Build gate: runner isolato, permessi minimi, scansione di codice, segreti e dipendenze.
- Artifact gate: hash, firma, SBOM o provenance e registry controllato.
- Deploy gate: ambiente autorizzato, identità temporanea, approval e rollback.
Checklist per un team piccolo
- I workflow richiedono review di un proprietario tecnico?
- Le azioni terze sono fissate a revisioni immutabili?
- Ogni job dichiara permessi minimi?
- Le pull request non fidate sono isolate dai segreti?
- Le credenziali cloud sono temporanee o ruotate?
- Il deploy usa esattamente l’artefatto testato?
- Produzione richiede condizioni e approvazione documentate?
- Log, alert e rollback vengono provati periodicamente?
Errori frequenti
- Affidarsi a un solo scanner: non copre identità, flussi e integrità degli artefatti.
- Usare un token amministratore ovunque: trasforma ogni job in un punto critico.
- Fidarsi dei tag: comodità e immutabilità non sono la stessa cosa.
- Inserire segreti nell’immagine: il valore può restare nei layer anche se rimosso dopo.
- Approvare senza evidenze: il controllo manuale diventa rituale.
Domande frequenti
La CI/CD è necessaria anche per un sito piccolo?
Non sempre serve una piattaforma complessa, ma un rilascio ripetibile con backup, test, credenziali separate e rollback riduce errori anche nei progetti piccoli.
SHA completo o tag per le azioni?
Lo SHA completo offre un riferimento immutabile. Il tag è più semplice da leggere, ma richiede fiducia nell’autore e può essere spostato.
Che cosa controllare per primo?
Chi può modificare i workflow, quali segreti sono disponibili e quali job possono raggiungere produzione. Sono i percorsi con impatto maggiore.
Conclusione
Mettere in sicurezza la CI/CD significa ridurre il potere di ogni passaggio e verificare ciò che attraversa la pipeline. Dipendenze immutabili, identità temporanee, artefatti attestati e cancelli di deployment creano una catena più veloce da usare e più difficile da compromettere.