Che cosa fa nascere un alert e che cosa apre una pull request
Un Dependabot alert nasce dall’incrocio fra due cose: il dependency graph del repository da un lato e il GitHub Advisory Database dall’altro. Tre eventi possono farlo comparire: una nuova vulnerabilità entra nel database, l’azienda pubblica un innersource advisory per una dipendenza che usi, oppure cambia il dependency graph, per esempio perché un commit aggiorna un pacchetto o una versione. Nella nomenclatura odierna queste funzionalità stanno sotto Supply Chain Security, accanto a GitHub Secret Protection e GitHub Code Security nell’ombrello delle GitHub Security suites: la certificazione conserva il nome storico GitHub Advanced Security, i prodotti no.
Prima distinzione da tenere ferma: non tutti gli advisory producono alert. Quelli reviewed da GitHub sì, gli innersource sì, i malware advisory sì quando i malware alert sono attivi sul repository. Gli advisory unreviewed, importati automaticamente dal National Vulnerability Database, non generano alert perché non sono stati verificati per validità e completezza. È un punto che l’esame ama, perché è controintuitivo: la vulnerabilità è visibile nel database ma non entra nella tua coda di lavoro.
Se sul repository sono attivi i Dependabot security updates, l’alert non resta una notifica. Dependabot prova ad aprire una pull request per ogni alert aperto che abbia una patch disponibile, portando la dipendenza alla versione minima che contiene la correzione, e lo fa solo per dipendenze dichiarate in un manifest o in un lock file. Da non confondere con i version updates, che sono un meccanismo diverso: si dichiarano nel file dependabot.yml e aggiornano le dipendenze anche quando non esiste nessuna vulnerabilità.
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
Questo blocco governa i version updates. I security updates non hanno bisogno di una voce qui: nascono dall’alert, non dalla pianificazione.
Prioritizzare: EPSS non è la gravità
Nella lista degli alert l’ordinamento predefinito è Most important, che combina segnali come il punteggio CVSS, lo scope della dipendenza e il fatto che siano state rilevate chiamate alla funzione vulnerabile. Sopra questo ordinamento lavori con i filtri: severity, scope per separare le dipendenze di sviluppo da quelle di runtime, ecosystem, resolution, has:patch per isolare ciò che è davvero risolvibile oggi.
Il filtro che cambia la conversazione è però epss_percentage. EPSS è un punteggio da 0 a 100% che stima la probabilità che quella vulnerabilità venga sfruttata nei trenta giorni successivi; è mantenuto dal Forum of Incident Response and Security Teams e viene ricalcolato ogni giorno. CVSS misura una cosa diversa: quanto sarebbe grave l’impatto se lo sfruttamento avvenisse. Le due scale non si sostituiscono. Una vulnerabilità con CVSS alto ed EPSS trascurabile è un rischio teorico serio ma poco probabile; una con gravità media ed EPSS alto è quella che qualcuno sta già usando in rete. La coda sensata si costruisce leggendo entrambe, e il modo tipico in cui l’esame verifica il concetto è chiederti quale metrica indica la probabilità di sfruttamento: la risposta è EPSS, mai CVSS.
Auto-triage: chiudere da sole le cose che non meritano lavoro
Le auto-triage rule riducono il rumore prima ancora che diventi rumore, perché vengono applicate prima dell’invio delle notifiche. Le GitHub preset rule sono curate da GitHub: la più nota, Dismiss low impact issues for development-scoped dependencies, chiude gli alert su dipendenze npm con scope di sviluppo che ricadono in una lista definita di CWE a basso impatto, ed è attiva per impostazione predefinita sui repository pubblici. Esiste anche un preset dedicato ai malware alert.
Le custom rule le scrivi tu, filtrando su metadati come CVE ID, GHSA ID, CWE, dependency scope, ecosystem, package name, manifest path, disponibilità della patch, severity e punteggio EPSS. Le azioni possibili sono due: chiudere l’alert, in modo indefinito oppure fino a quando una patch diventa disponibile, oppure far aprire a Dependabot una pull request, opzione disponibile solo se i security updates sono disattivati sul repository. Sui repository privati e internal le custom rule richiedono GitHub Code Security; sui pubblici sono a disposizione.
Qui si inserisce una distinzione che vale la pena memorizzare: le auto-triage rule dell’organizzazione vivono nei global settings, insieme ai custom pattern di Secret Protection, non dentro una security configuration. La security configuration è l’insieme di interruttori che applichi ai repository per dire quali funzionalità sono accese; i global settings definiscono come quelle funzionalità si comportano. A livello di organizzazione una regola può essere Enabled, e allora l’amministratore del repository può disattivarla, oppure Enforced, e allora non può.
Chiuso da solo, chiuso a mano, e il ruolo delle campagne
Un alert chiuso da una regola porta la risoluzione Auto-dismissed, tracciata in webhook, API e audit log. Per vederlo devi togliere il filtro is:open e poi scegliere Closed as e Auto-dismissed. La differenza sostanziale rispetto a una chiusura manuale è che l’auto-dismiss può riaprirsi da solo quando cambiano i metadati, per esempio se una dipendenza passa da development a produzione. La chiusura manuale è invece una decisione umana e resta tale; su di essa può agire il delegated alert dismissal, che obbliga chi ha accesso in scrittura a chiedere l’approvazione di un owner o security manager e che, attenzione, è cosa diversa dal delegated bypass, il quale riguarda chi può pushare un segreto bloccato da push protection.
Infine le security campaign, create dalla scheda Security dell’organizzazione da owner e security manager, con un referente indicato e una due date: raggruppano fino a mille alert e li consegnano agli sviluppatori come lavoro condiviso. La confusione tipica da evitare è credere che servano per svuotare centinaia di alert di dipendenze: la documentazione le descrive per gli alert di code scanning e per quelli di secret scanning, mentre sul lato supply chain le leve di scala restano i filtri della security overview, le auto-triage rule e le pull request di security update.