CVE e CWE: l’istanza e la classe
Un CVE (Common Vulnerabilities and Exposures) identifica una vulnerabilità concreta e specifica: quel pacchetto, quelle versioni, quel difetto. Un CWE (Common Weakness Enumeration) identifica invece la classe di debolezza a cui il difetto appartiene, per esempio l’iniezione SQL o il cross-site scripting, a prescindere da dove si manifesta. Servono entrambi perché rispondono a domande diverse: il CVE dice che una dipendenza va aggiornata, il CWE dice che un certo tipo di errore ricorre nel codice e va corretto alla radice, anche in punti dove nessuno ha ancora pubblicato niente.
La distinzione non è accademica, è visibile nel prodotto. Gli alert generati da GitHub Code Security (il nome attuale di quello che storicamente si chiamava code scanning con CodeQL) espongono una security severity ricavata proprio dai CWE: GitHub cerca i CVE che portano gli stessi tag CWE associati alla query e usa i loro punteggi per attribuire il livello Critical, High, Medium o Low. Il CWE è quindi l’anello che collega un’analisi statica al mondo reale delle vulnerabilità pubblicate. Nel GitHub Advisory Database lo stesso legame è navigabile: fra i qualificatori di ricerca c’è cwe:ID, accanto a severity:, ecosystem:, affects: e is:withdrawn.
GHSA: l’identificatore che non manca mai
Ogni advisory nel database riceve un GHSA ID nella forma GHSA-xxxx-xxxx-xxxx. È il punto che confonde più spesso: il CVE può mancare, arrivare dopo o non essere mai richiesto, mentre il GHSA c’è sempre. Gli advisory sono pubblicati come file JSON nel formato OSV (Open Source Vulnerability) e si dividono in tre categorie che vanno tenute separate:
- reviewed: verificati da GitHub e mappati sui pacchetti degli ecosistemi supportati;
- unreviewed: importati automaticamente dal feed del National Vulnerability Database, senza controllo di validità o completezza;
- malware: pacchetti malevoli segnalati dal team di sicurezza npm e da OpenSSF, dove spesso non esiste una versione sicura e l’unica strada è smettere di usare il pacchetto.
Solo gli advisory revisionati da GitHub, e gli innersource advisories pubblicati dalla propria impresa, generano alert di vulnerabilità sui repository. Gli advisory malware non restano muti: producono i malware alerts dedicati, oggi limitati all’ecosistema npm. Gli unreviewed sono l’unica categoria che non genera alcun alert. Gli innersource advisory usano un formato analogo a quello pubblico ma non sono visibili all’esterno e propagano alert solo dentro l’enterprise che li ha pubblicati.
# schema mentale degli identificatori di un advisory
ghsa_id: GHSA-xxxx-xxxx-xxxx # sempre presente
cve_id: CVE-2020-28482 # solo se assegnato
cwe: CWE-79 # la classe di debolezza
severity: high # derivata dal punteggio CVSS
Divulgazione coordinata e repository security advisory
La divulgazione coordinata è uno sforzo congiunto fra chi segnala e chi mantiene il progetto: la segnalazione iniziale resta privata e i dettagli completi diventano pubblici quando esiste una correzione. Il punto di partenza è un file SECURITY.md, che dichiara come e dove ricevere le segnalazioni, così da non costringere il ricercatore a cercare contatti nella storia di Git.
Con private vulnerability reporting abilitato, chiunque può inviare una segnalazione dalla scheda Security con il pulsante Report a vulnerability: il ricercatore diventa collaboratore della proposta di advisory e ha un credito in sospeso. Il maintainer lavora su una repository security advisory in bozza, discute l’impatto in privato e può aprire un temporary private fork per preparare la correzione senza esporla. Prima di pubblicare va indicata la versione che risolve il problema, altrimenti gli utenti riceveranno un alert senza avere una versione sicura verso cui aggiornare. Se manca il CVE lo si può chiedere con Request CVE, perché GitHub è CVE Numbering Authority. La pubblicazione elimina il fork temporaneo, rende visibile l’advisory e apre la revisione da parte di GitHub, che può portarlo nel database globale e da lì generare alert sui repository che usano il pacchetto.
Dall’alert alla correzione: il percorso completo
Il triage inizia dalla priorità, e qui vanno tenuti distinti due numeri. CVSS misura la gravità intrinseca della vulnerabilità; EPSS stima la probabilità che venga sfruttata ed è aggiornato quotidianamente. Un CVSS alto con EPSS basso e un CVSS medio con EPSS alto raccontano storie diverse: l’uno non sostituisce l’altro. Si guardano poi la disponibilità di una patch e il fatto che la dipendenza finisca davvero negli artefatti distribuiti.
La correzione arriva dagli aggiornamenti di sicurezza di Supply Chain Security per le dipendenze e dalle correzioni suggerite sugli alert di codice; a scala si usano le security campaigns, che raggruppano alert e li affidano a un punto di contatto nominato. Chiudere un alert senza correggerlo è invece un atto di governance: con la delegated alert dismissal chi ha accesso in scrittura deve richiedere la chiusura, e organization owner e security manager approvano o rifiutano; copre alert di codice, di segreti e di dipendenze. Non va confusa con la delegated bypass della push protection, che riguarda chi può spingere un commit contenente un segreto bloccato tramite una bypass list. Una regola vale per gli alert già aperti, l’altra per il push che li creerebbe.
Sul piano organizzativo, ricorda che una security configuration è l’insieme di interruttori applicato ai repository, mentre custom pattern e auto-triage rule vivono nei global settings dell’organizzazione. E che sui repository pubblici queste funzionalità sono disponibili senza costo, mentre su repository privati e internal servono le licenze GitHub Code Security e GitHub Secret Protection. L’esame insiste su tre punti: il GHSA esiste sempre e il CVE no, gli unreviewed non generano alert, e dismissal e bypass non sono la stessa delega.