Definire la gravità, poi renderla vincolante
Su un’organizzazione grande la coda degli alert non si smaltisce leggendola: si smaltisce decidendo in anticipo che cosa merita di bloccare una merge e che cosa può aspettare. Il primo errore è confondere due grandezze diverse. La severity di un alert di Supply Chain Security deriva dal punteggio CVSS, che misura quanto sarebbe grave lo sfruttamento; l’EPSS stima invece la probabilità che quella vulnerabilità venga sfruttata nei trenta giorni successivi, ed è espresso sia come punteggio percentuale sia come percentile rispetto alle altre. Sono ortogonali: una vulnerabilità critical con EPSS bassissimo e una high con EPSS alto raccontano due rischi diversi. Nella lista degli alert Dependabot il filtro epss_percentage accetta confronti, per esempio epss_percentage:>0.01, mentre severity resta un filtro a sé.
In Security overview la stessa logica si applica trasversalmente all’organizzazione: si combinano qualificatori come severity, has:patch (utile per separare ciò che è correggibile subito da ciò che non ha ancora una patch), team, visibility e repo per costruire la coda su cui si lavorerà davvero.
Definire le soglie però non basta: vanno rese effettive. Questo avviene con i ruleset, non con le vecchie branch protection e non come status check. Nel ruleset si attiva Require code scanning results, si aggiunge lo strumento (per esempio CodeQL) sotto Required tools and alert thresholds e si impostano due soglie distinte: Alerts, con valori None, Errors, Errors and Warnings, All, e Security alerts, con valori None, Critical, High or higher, Medium or higher, All. La merge viene bloccata in tre casi: lo strumento richiesto trova un alert di una severità definita nel ruleset, la sua analisi è ancora in corso, oppure lo strumento non è configurato sul repository. Due precisazioni che l’esame ama: le righe di codice indicate dall’alert devono esistere nel diff della pull request perché il blocco scatti, e i ruleset si creano a livello di repository oppure a livello di organizzazione con i piani Enterprise.
Le campagne: un referente, una scadenza, un perimetro
Le security campaigns trasformano un filtro in un pezzo di lavoro assegnabile: raggruppano alert di Code Security e di Secret Protection e li condividono con chi deve correggerli. Si parte da un campaign template oppure da filtri personalizzati; i template per il codice includono solo tipi di alert per cui è supportato Copilot Autofix, proprio perché la campagna nasce per essere chiusa in fretta. Ogni campagna ha un campaign manager, che deve essere un utente o un team con ruolo di owner o di security manager dell’organizzazione, e può avere una due date e un Contact link per raggiungere il referente. Esistono un tetto al numero di alert per campagna e un tetto alle campagne attive contemporaneamente: se serve di più, si segmenta.
Per chi ha accesso in scrittura la campagna compare nella scheda Security and quality del repository e arriva per email con un link diretto. Attenzione alla differenza di requisiti: per le campagne su alert di codice le notifiche raggiungono chi ha write access al repository, mentre per quelle su Secret Protection basta l’accesso in visualizzazione alla lista degli alert. Lo sviluppatore vede se qualcuno sta già lavorando su un alert (branch o pull request in corso), può applicare l’autofix, oppure assegnare in blocco un gruppo di alert a Copilot perché li risolva in un’unica pull request. Il monitoraggio distingue quattro stati: Open, In progress (solo campagne di codice), Fixed e Dismissed. A lavoro finito la campagna va chiusa, non cancellata: resta consultabile fra quelle chiuse e può essere riaperta, mentre l’eliminazione butta via anche i dati.
Gestione in blocco e chiusura automatica
Sul singolo repository gli alert di code scanning si chiudono anche in blocco: si filtra la lista (per esempio per una CWE) e si applica lo stesso motivo a tutti. Una chiusura vale su tutti i branch.
Sul lato dipendenze la leva è quella delle auto-triage rule, che agiscono prima che le notifiche vengano inviate. Ci sono preset curati da GitHub, come Dismiss low impact issues for development-scoped dependencies, attivo per impostazione predefinita sui repository pubblici e da abilitare esplicitamente sui privati, e Dismiss package malware alerts, disattivato per impostazione predefinita. Le regole personalizzate si costruiscono su metadati come severity, EPSS score, dependency scope, ecosystem, package name, CWE, manifest path e disponibilità della patch, e possono chiudere l’alert in modo definitivo, rinviarlo finché non esiste una patch, oppure aprire una pull request. Valgono sia sugli alert futuri sia su quelli già presenti. Qui entra la distinzione che l’esame verifica spesso: le auto-triage rule e i custom pattern stanno nei global settings dell’organizzazione, mentre le security configuration sono i pacchetti di interruttori che si applicano ai repository. Una regola definita a livello di organizzazione può essere resa vincolante o solo proposta, e in caso di conflitto prevale su quella del repository.
Documentare, o pagare al prossimo audit
Un alert chiuso senza traccia del perché è un debito. Le regole automatiche non lo cancellano: gli alert auto-chiusi restano interrogabili, con motivo di chiusura dedicato, via interfaccia (togliendo il filtro predefinito sugli alert aperti e selezionando la chiusura automatica), API, webhook e audit log, e possono essere riaperti. Sulle chiusure manuali il commento di dismissal finisce nella timeline dell’alert ed è esattamente il materiale che servirà in fase di audit.
Infine il controllo umano, dove si annida la confusione più tipica. La delegated alert dismissal limita chi può chiudere direttamente un alert: chi ha accesso in scrittura invia una richiesta, owner e security manager (o ruoli personalizzati abilitati) approvano o negano, con notifica via email; copre Code Security, Secret Protection e Dependabot. Il delegated bypass riguarda tutt’altro momento: chi può spingere un commit che la push protection ha bloccato. Uno governa la chiusura di un alert esistente, l’altro l’ingresso di un segreto nel repository. Se in una domanda compare la parola “push”, non è dismissal.