Leggere il risultato: il percorso da source a sink

Un alert prodotto da CodeQL, il motore di GitHub Code Security (il prodotto storicamente noto come code scanning), non è una segnalazione su una riga: quando la query è di tipo dataflow porta con sé la catena che collega un dato non fidato a un’operazione pericolosa. Sulla pagina dell’alert il comando è Show paths: quella vista è un elenco numerato dei passaggi del flusso, dal punto in cui il dato fornito dall’utente entra nel codice (il source) fino al punto in cui viene usato in un’operazione potenzialmente non sicura (il sink).

Leggere il percorso è l’unico modo per decidere se il finding è reale: se fra source e sink c’è una sanitizzazione che CodeQL non riconosce, hai un falso positivo argomentabile; se ogni passaggio è pura propagazione, il finding è vero. Quando più cammini portano allo stesso sink, un menu a tendina li mostra uno per uno: i percorsi correlati stanno sotto un unico alert. Show more apre la descrizione della regola con le indicazioni su come correggere. Nelle pull request l’alert compare come annotazione nel tab Files changed, con lo stesso Show paths.

Gravità, categorie e filtri

Due scale convivono. Tutti gli alert hanno livello Error, Warning o Note; quelli trovati da CodeQL hanno in più una security severity Critical, High, Medium o Low, basata su CVSS, che viene mostrata e usata al posto della severity generica. Confusione classica da evitare: CVSS misura la gravità, non la probabilità che il difetto venga sfruttato. Quella probabilità è EPSS e appartiene agli alert di Supply Chain Security, non a code scanning.

Le categorie sono un’altra cosa: il codice non applicativo è etichettato come Generated, Test, Library o Documentation, per percorso del file e senza intervento manuale possibile. Puoi però filtrare con autofilter:true per vedere solo il codice applicativo. I filtri si combinano in AND — is:closed severity:high branch:main — tranne quelli di branch, che si combinano in OR.

Ciclo di vita, autofix e chi può chiudere

La pagina di un alert riflette lo stato sul branch di default; gli altri stanno in Affected branches. Due regole vanno sapute a memoria, perché l’esame ci gioca sopra: quando chiudi un alert viene chiuso su tutti i branch, e alla successiva esecuzione di code scanning lo stesso codice non genererà un alert. Non è una chiusura limitata a un branch né una sospensione temporanea. La ragione scelta nel menu a tendina può inoltre influire sul fatto che quella query resti inclusa nelle analisi future; il commento facoltativo finisce nella timeline dell’alert e vale come giustificazione in sede di audit. Un alert chiuso si riapre dalla lista dei closed.

Chi può chiudere è governato da delegated alert dismissal: chi ha permesso di scrittura non chiude più direttamente ma inoltra una richiesta, e i reviewer — di default organization owner e security manager — approvano o negano, con notifica email a entrambe le parti. Copre code scanning, secret scanning e Dependabot. Non confonderlo con il delegated bypass, che appartiene a GitHub Secret Protection e riguarda chi può completare un push bloccato da push protection: uno decide chi può pubblicare un segreto, l’altro chi può chiudere una segnalazione.

Copilot Autofix genera un’unica proposta di correzione per un alert, che sei tu a rivedere e applicare. Non richiede un abbonamento Copilot e non consuma crediti AI; è gratuito sui repository pubblici, mentre su privati e internal serve una licenza GitHub Code Security. Nella pull request puoi accettarla, modificarla nell’editor web o in locale con GitHub CLI, testarla e ripubblicarla per far rigirare l’analisi, oppure scartarla con Dismiss suggestion. Valutala chiedendoti se interrompe davvero il percorso dataflow senza cambiare il comportamento funzionale.

Diagnosticare una scansione che non funziona

Il punto di partenza è la tool status page del repository: dichiara se le configurazioni funzionano, richiedono attenzione o non funzionano, e mostra la copertura dei file per linguaggio, dove uno zero significa che quel linguaggio non viene analizzato. Poi si scende nel log del job di analisi nel tab Actions.

Ogni errore ricorrente ha un punto di partenza preciso. Automatic build failed for a compiled language vuol dire che autobuild non ha compilato: si passa alla build manuale rimuovendo quello step e scrivendo i propri comandi, e serve advanced setup, perché il default setup non espone un workflow modificabile. No source code was seen during the build ha diverse cause: nessun linguaggio supportato, compilazione fallita, build servita da cache, oppure compilazione avvenuta fuori dagli step init e analyze o dentro un container separato. Some languages were not analyzed dipende dal fatto che senza matrice, fra i linguaggi compilati, CodeQL analizza solo quello con più file sorgente.

strategy:
  matrix:
    language: [ java-kotlin, javascript-typescript ]
steps:
  - uses: github/codeql-action/init@v3
    with:
      languages: ${{ matrix.language }}

Un’analisi troppo lunga si affronta con runner più grandi, matrice per parallelizzare i linguaggi, meno codice per esecuzione, spostamento sull’evento schedule — mantenendo almeno un workflow schedulato che analizza tutto il codice — e nessuna query oltre la default query suite. Gli errori di memoria o disco esauriti indicano runner che non rispettano i requisiti hardware raccomandati: larger runner o self-hosted. Se invece gli alert ci sono ma sono strani, sospetta la configurazione: abilitare il default setup disattiva il workflow CodeQL esistente e blocca il caricamento dei risultati via API, più configurazioni attive producono alert duplicati e le configurazioni obsolete lasciano alert aperti a tempo indefinito.