Ogni job GitHub Actions riceve un token. GitHub crea un nuovo GITHUB_TOKEN all'inizio di ogni job, limitato al repository in cui si trova il workflow, e qualsiasi step del job può usarlo. Ciò che può fare dipende da impostazioni che molti team non hanno mai guardato, e nei repository più vecchi la risposta è ancora "scrivere quasi ovunque".

Questo conta quando qualcosa nel job diventa malevolo. Nella compromissione "s1ngularity" di Nx di agosto 2025, il token del repository aveva ancora permessi di lettura e scrittura. Un'injection in un workflow pull_request_target lo ha usato per attivare il workflow di pubblicazione, che ha fatto trapelare il token npm usato per pubblicare versioni malevole di Nx. Un token di sola lettura avrebbe fermato quel passaggio.

Questo articolo spiega come si impostano i permessi del token, di che cosa ha bisogno ogni attività comune e come trovare il minimo per i Suoi workflow.

Che cos'è GITHUB_TOKEN

GITHUB_TOKEN è un installation access token dell'app GitHub Actions. Alcune proprietà sfuggono facilmente:

  • Esiste che Lei lo usi o no. I workflow vi fanno riferimento come secrets.GITHUB_TOKEN, ma qualsiasi action può leggerlo tramite il contesto github.token senza che le venga passato.
  • Viene scritto su disco per impostazione predefinita. actions/checkout conserva il token per i successivi comandi git, a meno che non imposti persist-credentials: false. Prima della v6 finiva in .git/config; la v6 lo ha spostato in un file separato sotto $RUNNER_TEMP. Nel 2024 la ricerca ArtiPACKED di Unit 42 ha trovato token trapelati attraverso artefatti che includevano .git/config.
  • Scade con il job. Sui runner ospitati da GitHub significa al massimo 6 ore, il limite di tempo del job. Sui runner self-hosted può essere rinnovato per un massimo di 24 ore.

Poiché il token è sempre presente, l'unica cosa che Lei controlla è quanto può fare.

L'impostazione predefinita: permissive o restricted

Ogni enterprise, organizzazione e repository ha un'impostazione predefinita per il token:

  • Permissive: lettura e scrittura su ogni permesso.
  • Restricted: sola lettura su contents e packages, nient'altro.

Dal 2 febbraio 2023, le nuove enterprise, organizzazioni e repository usano restricted come impostazione predefinita. La modifica non ha toccato quelli esistenti, quindi qualsiasi repository o organizzazione creato prima di allora mantiene l'impostazione permissive a meno che qualcuno non l'abbia cambiata. Se un livello superiore sceglie restricted, i livelli sottostanti non possono scegliere permissive.

Lo verifichi in Settings → Actions → General → Workflow permissions, partendo dal livello di organizzazione. La stessa sezione contiene Allow GitHub Actions to create and approve pull requests, che dovrebbe restare disattivata a meno che un workflow non ne abbia bisogno.

La chiave permissions

La chiave permissions in un workflow modifica il token rispetto all'impostazione predefinita. Funziona a due livelli:

permissions:
  contents: read

jobs:
  release:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<full-commit-sha>

Le regole:

  • Il livello di job prevale sul livello di workflow. Imposti il valore predefinito del workflow su sola lettura e aumenti i permessi solo nei job che ne hanno bisogno.
  • Tutto ciò che non elenca diventa none. Non appena imposta un permesso, tutti gli altri vengono rimossi. permissions: {} li rimuove tutti.
  • I valori sono read, write o none. write include read. read-all e write-all impostano tutto in una volta; eviti write-all.

I permessi disponibili, a settembre 2026:

PermessoChe cosa controlla
actionsEsecuzioni dei workflow, artefatti e cache
artifact-metadataRecord di metadati degli artefatti (ha sostituito contents per queste API nel 2026)
attestationsAttestazioni degli artefatti
checksCheck run e check suite
code-qualityRisultati sulla qualità del codice, come i report di copertura
contentsContenuti del repository, commit, branch, tag e release
deploymentsDeployment
discussionsDiscussioni
id-tokenRichiesta di un token OIDC (solo write o none)
issuesIssue e commenti
packagesGitHub Packages, compreso il container registry
pagesBuild di GitHub Pages
pull-requestsPull request, etichette e revisioni
security-eventsAvvisi di code scanning e caricamenti SARIF
statusesStati dei commit
vulnerability-alertsAvvisi di Dependabot (solo read o none)

Quando a un job manca un permesso necessario, la chiamata API fallisce con 403 Resource not accessible by integration. Quell'errore è il segnale per aggiungere l'unico permesso di cui lo step ha bisogno, non per passare a write-all.

Di che cosa hanno bisogno le attività comuni

AttivitàPermessi
Fare il checkout del codicecontents: read
Creare una release o fare il push di un tagcontents: write
Commentare una issue o una pull requestissues: write (i commenti sulle pull request passano dall'API delle issue)
Aggiungere etichette o revisioni a una pull requestpull-requests: write
Autenticarsi a un cloud provider con OIDCid-token: write
Creare attestazioni degli artefattiid-token: write, attestations: write, contents: read, più packages: write per le immagini container
Fare il push di un'immagine su GitHub Container Registrypackages: write
Caricare SARIF nel code scanningsecurity-events: write
Distribuire GitHub Pages da un workflowpages: write, id-token: write

La maggior parte dei job di test e di build non ha bisogno di nulla oltre a contents: read.

Fork, pull_request_target e Dependabot

  • Le pull request dai fork ricevono un token di sola lettura sull'evento pull_request, qualunque cosa chieda il workflow, a meno che un amministratore non attivi "Send write tokens to workflows from pull requests". La lasci disattivata.
  • pull_request_target riceve un token di lettura e scrittura anche per le pull request da fork pubblici. Per questo è all'origine di molti dei furti di token più noti: la compromissione di Nx, quella di Ultralytics a dicembre 2024 e quella dell'action Trivy a marzo 2026 sono tutte partite da un workflow pull_request_target. GitHub lo sta restringendo: da luglio 2026 actions/checkout rifiuta per impostazione predefinita di fare il checkout di codice dei fork in questi workflow e, dal 2 novembre 2026, nei repository pubblici senza una propria policy pull_request_target sarà disabilitato per impostazione predefinita.
  • Le pull request di Dependabot sono trattate come i fork: un token di sola lettura e nessun secret di Actions. Se sta valutando altri strumenti di aggiornamento, veda le alternative a Dependabot.

Come trovare i permessi minimi

Non deve ricavarli leggendo il codice sorgente di ogni action:

  • actions-permissions di GitHub Security Lab monitora come un workflow usa il suo token e consiglia i permessi minimi. È in beta pubblica.
  • Il controllo Token-Permissions di OpenSSF Scorecard segnala i workflow che non impostano permessi di sola lettura al livello superiore. Classifica il controllo come ad alto rischio.
  • zizmor, un analizzatore statico per i workflow, segnala i permessi eccessivi o predefiniti e i checkout che conservano le credenziali.
  • Secure-Repo e Harden-Runner di StepSecurity consigliano permessi a livello di job a partire da una knowledge base di action e dalle chiamate API effettuate da un job.

Un rollout pratico: imposti su restricted il valore predefinito dell'organizzazione, aggiunga permissions: contents: read all'inizio di ogni workflow ed esegua i workflow. Quelli che falliscono con Resource not accessible by integration Le dicono esattamente quale job ha bisogno di quale permesso aggiuntivo.

Il ruolo di CRACI

Il privilegio minimo limita ciò che può fare un token rubato. Non ne impedisce il furto, e gli altri secret del job, come i token npm e le credenziali cloud, sono altrettanto esposti.

CRACI esegue i Suoi job GitHub Actions sui propri runner. Lei cambia runs-on in craci; GITHUB_TOKEN, la chiave permissions e le impostazioni del Suo repository funzionano come prima, perché è sempre GitHub a emettere il token. Ciò che CRACI aggiunge sta sul runner: una policy di egress che decide quali host può raggiungere un job, viene convalidata prima dell'avvio del job e opera in modalità fail closed, e un registro di ogni pacchetto scaricato dal job, con una traccia delle sue connessioni di rete. Se codice malevolo in un job riesce a impossessarsi di un token, la policy limita dove può inviarlo e il registro mostra che cosa è successo.

Per il resto dei secret del job, veda Secret di GitHub Actions: come trapelano e come proteggerli. Prenoti una demo per vedere il registro di una delle Sue build.