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 Kontextgithub.tokenlesen, ohne dass es ihr übergeben wird. - Es wird standardmäßig auf die Festplatte geschrieben.
actions/checkoutspeichert das Token für spätere Git-Befehle, sofern Sie nichtpersist-credentials: falsesetzen. Vor v6 landete es in.git/config; v6 hat es in eine separate Datei unter$RUNNER_TEMPverschoben. 2024 fand die ArtiPACKED-Forschung von Unit 42 Tokens, die über Artefakte mit.git/configabflossen. - 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
contentsundpackages, 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,writeodernone.writeschließtreadein.read-allundwrite-allsetzen alles auf einmal; vermeiden Siewrite-all.
Die verfügbaren Berechtigungen, Stand September 2026:
| Berechtigung | Steuert |
|---|---|
actions | Workflow-Läufe, Artefakte und Caches |
artifact-metadata | Metadatensätze zu Artefakten (ersetzte 2026 contents für diese APIs) |
attestations | Artefakt-Attestierungen |
checks | Check Runs und Check Suites |
code-quality | Ergebnisse zur Codequalität, etwa Coverage-Berichte |
contents | Repository-Inhalte, Commits, Branches, Tags und Releases |
deployments | Deployments |
discussions | Discussions |
id-token | Anfordern eines OIDC-Tokens (nur write oder none) |
issues | Issues und Kommentare |
packages | GitHub Packages, einschließlich der Container Registry |
pages | GitHub-Pages-Builds |
pull-requests | Pull Requests, Labels und Reviews |
security-events | Code-Scanning-Warnungen und SARIF-Uploads |
statuses | Commit-Status |
vulnerability-alerts | Dependabot-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
| Aufgabe | Berechtigungen |
|---|---|
| Code auschecken | contents: read |
| Release erstellen oder Tag pushen | contents: write |
| Issue oder Pull Request kommentieren | issues: write (Kommentare zu Pull Requests laufen über die Issues-API) |
| Labels oder Reviews zu einem Pull Request hinzufügen | pull-requests: write |
| Per OIDC bei einem Cloud-Anbieter authentifizieren | id-token: write |
| Artefakt-Attestierungen erstellen | id-token: write, attestations: write, contents: read, dazu packages: write für Container-Images |
| Image in die GitHub Container Registry pushen | packages: write |
| SARIF ins Code Scanning hochladen | security-events: write |
| GitHub Pages aus einem Workflow deployen | pages: 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_requestein 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_targeterhä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 einempull_request_target-Workflow. GitHub schränkt das zunehmend ein: Seit Juli 2026 weigert sichactions/checkoutstandardmäßig, Fork-Code in diesen Workflows auszuchecken, und ab dem 2. November 2026 istpull_request_targetin ö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.
