Default setup e advanced setup

La certificazione si chiama ancora GitHub Advanced Security, ma il prodotto che analizza il codice sorgente oggi si chiama GitHub Code Security, dentro l’ombrello delle GitHub Security suites: è quello che la documentazione più vecchia descriveva come “code scanning con CodeQL”. Sui repository pubblici di GitHub.com l’analisi è gratuita; su repository privati e internal serve una licenza GitHub Code Security. È una distinzione che l’esame ama, perché è la stessa logica che vale per Secret Protection e per Supply Chain Security.

Il default setup è la via rapida: GitHub genera da solo la configurazione, senza che voi scriviate un workflow. Analizza i linguaggi supportati da CodeQL e viene eseguito a ogni push sul branch di default o su un branch protetto, sulle pull request verso il branch di default e con una cadenza settimanale. Dall’interfaccia potete comunque scegliere i linguaggi, la query suite e i threat model per Java/Kotlin e C#. Un limite da tenere a mente: se il repository non contiene alcun linguaggio supportato da CodeQL, il default setup non esegue nessuna scansione.

L’advanced setup entra in gioco quando le opzioni di personalizzazione del default setup, incluso il file di configurazione, non bastano. Qui definite un vostro workflow di GitHub Actions e ottenete quattro cose che il default setup non offre: passi di build espliciti per i linguaggi compilati, matrix build, una pianificazione delle scansioni decisa da voi e l’integrazione con una CI esterna. Sui linguaggi compilati la leva è il build mode: none costruisce il database direttamente dal codice ed è disponibile per tutti i linguaggi interpretati più C/C++, C#, Java e Rust; autobuild prova a indovinare il metodo di build; manual è la scelta obbligata quando la build è complessa o non standard, e richiede l’advanced setup.

CodeQL, strumenti di terze parti e il file SARIF

La scelta fra CodeQL e un analizzatore di terze parti non è esclusiva. CodeQL è il motore di analisi sviluppato da GitHub, con query mantenute da GitHub e dalla community, integrato nativamente con gli alert e con Copilot Autofix. Uno strumento esterno resta però utile quando copre un linguaggio o una classe di problemi che CodeQL non tratta, oppure quando l’azienda ha già un tool su cui ha investito. Il ponte fra i due mondi è SARIF, Static Analysis Results Interchange Format, uno standard JSON per i risultati dell’analisi statica: code scanning supporta la versione 2.1.0.

Ci sono tre strade per far arrivare i risultati dentro GitHub. La prima è far girare lo strumento dentro un workflow di Actions e caricarne l’output con l’action upload-sarif. La seconda è la CodeQL CLI, uno strumento a riga di comando autonomo: si crea il database con database create, si producono i risultati con database analyze e li si carica con github upload-results. La terza è l’API di code scanning, per tutti gli strumenti che generano risultati fuori dal repository.

La CLI è la risposta canonica alla domanda “come faccio se la mia pipeline non è su Actions”. Il bundle completo della CodeQL CLI deve essere disponibile su ogni server della CI, e ogni server ha bisogno di una GitHub App o di un personal access token con permesso di scrittura su security_events per caricare i risultati. Attenzione a una trappola tipica: se sul repository è attivo il default setup, un caricamento SARIF che contiene risultati CodeQL viene rifiutato con l’errore Upload with CodeQL results rejected due to 'default setup', perché GitHub evita di mostrare alert duplicati prodotti da due sistemi diversi. O disattivate CodeQL nel default setup, o disattivate il caricamento.

La category, ovvero come non sovrascrivere le proprie analisi

Il campo category è il concetto più frainteso di tutta l’unità. La documentazione lo definisce così: “Use the category to distinguish between multiple analyses for the same tool or commit, but performed on different languages or different parts of the code”. Finisce dentro runAutomationDetails.id, che viene interpretato come category/run-id: tutto ciò che precede l’ultima barra è la category.

Serve perché il caricamento di un secondo file SARIF per uno stesso commit è trattato come sostituzione del set di dati precedente. La sostituzione però non è cieca: opera all’interno della coppia strumento più category. Analisi con category diverse, o provenienti da tool diversi, convivono sullo stesso commit; due caricamenti con lo stesso tool e la stessa category si sovrascrivono a vicenda, e se accadono nello stesso workflow run GitHub riconosce l’errore di configurazione e fa fallire l’esecuzione.

È esattamente la chiave dei monorepo analizzati a fette: un servizio per volta, una category per servizio, e nessuna fetta cancella l’altra.

strategy:
  fail-fast: false
  matrix:
    include:
      - language: javascript-typescript
        build-mode: none
      - language: java-kotlin
        build-mode: manual
# nello step di analisi:
#   category: "/language:${{ matrix.language }}/service:billing"

Matrix build e frequenza di scansione

La matrix per linguaggio non è solo eleganza: fa girare in parallelo l’analisi di ogni linguaggio, quindi accorcia il tempo di attesa sulla pull request. Quando i tempi restano lunghi, le leve documentate sono runner più grandi con più RAM, CPU e disco, la riduzione del numero di query e la limitazione del codice analizzato.

Sulle query il compromesso è netto: la suite default è molto precisa e produce pochi falsi positivi, mentre security-extended aggiunge query con precisione e severità leggermente inferiori, quindi più alert ma anche più rumore.

La frequenza è un bilancio fra costo e tempestività. Analizzare ogni push e ogni pull request dà il feedback nel momento in cui serve, ma consuma minuti di Actions; spostare l’analisi al solo evento schedule costa poco e trova le vulnerabilità con giorni di ritardo. Nell’esame aspettatevi lo scenario inverso a quello che verrebbe istintivo: davanti a un monorepo con più linguaggi e a un requisito di blocco delle pull request, la risposta giusta quasi mai è “aumentare la frequenza”, ma “advanced setup, matrix per linguaggio, category distinte e trigger su pull request”.