Jeder GitHub-Actions-Job erhält ein Token. GitHub erstellt zu Beginn jedes Jobs ein neues GITHUB_TOKEN, beschränkt auf das Repository des Workflows, und jeder Schritt im Job kann es verwenden. Was es darf, hängt von Einstellungen ab, die viele Teams nie angesehen haben, und in älteren Repositories lautet die Antwort noch immer: fast überall schreiben.

Das ist wichtig, wenn etwas im Job bösartig wird. Bei der Nx-Kompromittierung „s1ngularity“ im August 2025 hatte das Token des Repositorys noch Lese- und Schreibrechte. Eine Injection in einem pull_request_target-Workflow nutzte es, um den Publish-Workflow auszulösen, der das npm-Token preisgab, mit dem bösartige Nx-Versionen veröffentlicht wurden. Ein Read-only-Token hätte diesen Schritt gestoppt.

Dieser Beitrag erklärt, wie die Berechtigungen des Tokens festgelegt werden, was jede gängige Aufgabe braucht und wie Sie das Minimum für Ihre Workflows finden.

Was GITHUB_TOKEN ist

GITHUB_TOKEN ist ein Installation Access Token der GitHub-Actions-App. Einige Eigenschaften werden leicht übersehen:

  • Es existiert, ob Sie es nutzen oder nicht. Workflows referenzieren es als secrets.GITHUB_TOKEN, aber jede Action kann es über den Kontext github.token lesen, ohne dass es ihr übergeben wird.
  • Es wird standardmäßig auf die Festplatte geschrieben. actions/checkout speichert das Token für spätere Git-Befehle, sofern Sie nicht persist-credentials: false setzen. Vor v6 landete es in .git/config; v6 hat es in eine separate Datei unter $RUNNER_TEMP verschoben. 2024 fand die ArtiPACKED-Forschung von Unit 42 Tokens, die über Artefakte mit .git/config abflossen.
  • Es läuft mit dem Job ab. Auf GitHub-hosted Runnern heißt das höchstens 6 Stunden, das Zeitlimit für Jobs. Auf selbst gehosteten Runnern kann es bis zu 24 Stunden lang erneuert werden.

Weil das Token immer da ist, können Sie nur steuern, wie viel es darf.

Der Standard: permissive oder restricted

Jede Enterprise, Organisation und jedes Repository hat einen Standard für das Token:

  • Permissive: Lesen und Schreiben bei jeder Berechtigung.
  • Restricted: Read-only bei contents und packages, sonst nichts.

Seit dem 2. Februar 2023 gilt für neue Enterprises, Organisationen und Repositories standardmäßig restricted. Die Änderung betraf bestehende nicht, sodass jedes vorher erstellte Repository und jede vorher erstellte Organisation den Standard permissive behält, sofern niemand ihn geändert hat. Wählt eine höhere Ebene restricted, können die Ebenen darunter nicht permissive wählen.

Prüfen Sie das unter Settings → Actions → General → Workflow permissions, zuerst auf Organisationsebene. Im selben Abschnitt finden Sie Allow GitHub Actions to create and approve pull requests, das deaktiviert bleiben sollte, sofern kein Workflow es braucht.

Der Schlüssel permissions

Der Schlüssel permissions in einem Workflow passt das Token gegenüber dem Standard an. Er wirkt auf zwei Ebenen:

permissions:
  contents: read

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

Die Regeln:

  • Die Job-Ebene überschreibt die Workflow-Ebene. Setzen Sie den Workflow-Standard auf Read-only und erhöhen Sie Berechtigungen nur in den Jobs, die sie brauchen.
  • Alles, was Sie nicht aufführen, wird zu none. Sobald Sie eine Berechtigung setzen, werden alle anderen entfernt. permissions: {} entfernt sie alle.
  • Die Werte sind read, write oder none. write schließt read ein. read-all und write-all setzen alles auf einmal; vermeiden Sie write-all.

Die verfügbaren Berechtigungen, Stand September 2026:

BerechtigungSteuert
actionsWorkflow-Läufe, Artefakte und Caches
artifact-metadataMetadatensätze zu Artefakten (ersetzte 2026 contents für diese APIs)
attestationsArtefakt-Attestierungen
checksCheck Runs und Check Suites
code-qualityErgebnisse zur Codequalität, etwa Coverage-Berichte
contentsRepository-Inhalte, Commits, Branches, Tags und Releases
deploymentsDeployments
discussionsDiscussions
id-tokenAnfordern eines OIDC-Tokens (nur write oder none)
issuesIssues und Kommentare
packagesGitHub Packages, einschließlich der Container Registry
pagesGitHub-Pages-Builds
pull-requestsPull Requests, Labels und Reviews
security-eventsCode-Scanning-Warnungen und SARIF-Uploads
statusesCommit-Status
vulnerability-alertsDependabot-Warnungen (nur read oder none)

Fehlt einem Job eine benötigte Berechtigung, schlägt der API-Aufruf mit 403 Resource not accessible by integration fehl. Dieser Fehler ist das Signal, die eine Berechtigung hinzuzufügen, die der Schritt braucht, nicht auf write-all umzustellen.

Was gängige Aufgaben brauchen

AufgabeBerechtigungen
Code auscheckencontents: read
Release erstellen oder Tag pushencontents: write
Issue oder Pull Request kommentierenissues: write (Kommentare zu Pull Requests laufen über die Issues-API)
Labels oder Reviews zu einem Pull Request hinzufügenpull-requests: write
Per OIDC bei einem Cloud-Anbieter authentifizierenid-token: write
Artefakt-Attestierungen erstellenid-token: write, attestations: write, contents: read, dazu packages: write für Container-Images
Image in die GitHub Container Registry pushenpackages: write
SARIF ins Code Scanning hochladensecurity-events: write
GitHub Pages aus einem Workflow deployenpages: write, id-token: write

Die meisten Test- und Build-Jobs brauchen nicht mehr als contents: read.

Forks, pull_request_target und Dependabot

  • Pull Requests aus Forks erhalten beim Event pull_request ein Read-only-Token, unabhängig davon, was der Workflow anfordert, sofern ein Admin nicht „Send write tokens to workflows from pull requests“ aktiviert. Lassen Sie das deaktiviert.
  • pull_request_target erhält ein Token mit Lese- und Schreibrechten, auch bei Pull Requests aus öffentlichen Forks. Deshalb steckt es hinter vielen der bekanntesten Token-Diebstähle: Die Nx-Kompromittierung, die Ultralytics-Kompromittierung im Dezember 2024 und die Kompromittierung der Trivy-Action im März 2026 begannen alle mit einem pull_request_target-Workflow. GitHub schränkt das zunehmend ein: Seit Juli 2026 weigert sich actions/checkout standardmäßig, Fork-Code in diesen Workflows auszuchecken, und ab dem 2. November 2026 ist pull_request_target in öffentlichen Repositories ohne eigene Policy standardmäßig deaktiviert.
  • Dependabot-Pull-Requests werden wie Forks behandelt: ein Read-only-Token und keine Actions-Secrets. Wenn Sie andere Update-Tools abwägen, lesen Sie Dependabot-Alternativen.

So finden Sie die minimalen Berechtigungen

Sie müssen das nicht herausfinden, indem Sie den Quellcode jeder Action lesen:

  • actions-permissions vom GitHub Security Lab überwacht, wie ein Workflow sein Token nutzt, und empfiehlt die minimalen Berechtigungen. Es befindet sich in der öffentlichen Beta.
  • Der Check Token-Permissions von OpenSSF Scorecard markiert Workflows, die auf oberster Ebene keine Read-only-Berechtigungen setzen. Er stuft den Check als hohes Risiko ein.
  • zizmor, ein statischer Analyzer für Workflows, markiert übermäßige oder Standardberechtigungen und Checkouts, die Zugangsdaten speichern.
  • Secure-Repo und Harden-Runner von StepSecurity empfehlen Berechtigungen auf Job-Ebene, anhand einer Wissensbasis zu Actions und der API-Aufrufe eines Jobs.

Ein praktischer Rollout: Setzen Sie den Organisationsstandard auf restricted, fügen Sie permissions: contents: read oben in jeden Workflow ein und führen Sie die Workflows aus. Workflows, die mit Resource not accessible by integration fehlschlagen, zeigen Ihnen genau, welcher Job welche zusätzliche Berechtigung braucht.

Wo CRACI ins Spiel kommt

Least Privilege begrenzt, was ein gestohlenes Token anrichten kann. Es verhindert nicht, dass es gestohlen wird, und die übrigen Secrets im Job, etwa npm-Tokens und Cloud-Zugangsdaten, sind genauso gefährdet.

CRACI führt Ihre GitHub-Actions-Jobs auf eigenen Runnern aus. Sie ändern runs-on auf craci; GITHUB_TOKEN, der Schlüssel permissions und Ihre Repository-Einstellungen funktionieren wie bisher, weil GitHub das Token weiterhin ausstellt. Was CRACI ergänzt, sitzt auf dem Runner: eine Egress-Richtlinie, die festlegt, welche Hosts ein Job erreichen darf, vor dem Start des Jobs validiert wird und im Zweifel blockiert, sowie eine Aufzeichnung jedes Pakets, das der Job geladen hat, mit einem Trace seiner Netzwerkverbindungen. Gelangt Schadcode in einem Job doch an ein Token, begrenzt die Richtlinie, wohin er es senden kann, und die Aufzeichnung zeigt, was passiert ist.

Zu den übrigen Secrets des Jobs siehe GitHub Actions Secrets: Wie sie abfließen und wie Sie sie absichern. Buchen Sie eine Demo, um die Aufzeichnung eines Ihrer eigenen Builds zu sehen.