Am 14. und 15. März 2025 zeigte CVE-2025-30066 bei tj-actions/changed-files, wie viel Schaden eine kompromittierte Drittanbieter-Action anrichten kann: Angreifer verschoben Tags der Action auf einen manipulierten Commit, woraufhin Secrets in Workflow-Logs ausgegeben wurden. Die betroffenen Versionen reichten bis 45.0.7; 46.0.1 gilt als gepatchte Version. Öffentliche Analysen sprachen von mehr als 23.000 potenziell betroffenen Repositories. Die NVD dokumentiert die Schwachstelle und empfiehlt die Aktualisierung oder das Entfernen der betroffenen Action-Nutzung.
Ein GitHub-Actions-Workflow, der Container baut, Terraform ausführt, Artefakte signiert oder Kubernetes-Manifeste ausrollt, ist Produktionsinfrastruktur. Das typische Risikomuster besteht aus Drittanbieter-Actions mit Referenzen wie @v4 oder @main, breiten GITHUB_TOKEN-Rechten und langlebigen Cloud-Zugangsdaten als Repository-Secrets. Für 2026 solltest du diese GitHub Actions Security Best Practices standardisieren: vollständige Commit-Hashes, restriktive GITHUB_TOKEN permissions, GitHub Actions OIDC statt langlebiger Cloud-Secrets und verpflichtende Reviews für Workflow-Änderungen.
Warum GitHub Actions Security 2026 auf deine Prioritätenliste gehört
CI/CD-Supply-Chain-Security betrifft nicht nur den Quellcode. Ein manipulierter Build-Job kann Container-Images verändern, Artefakte in eine Paket-Registry hochladen oder Deployments in AWS, Azure oder Google Cloud starten. Wenn ein Workflow Secrets lesen und in ein Cloud-Konto schreiben darf, hat er praktisch die Rechte eines Deployment-Servicekontos.
Prüfe zuerst Workflows, die bei push auf main, bei Releases, bei Environment-Deployments oder mit pull_request_target laufen. Diese Jobs haben häufig Zugriff auf Paket-Tokens, Container-Registries, Signaturschlüssel oder Cloud-Rollen.
Schritt 1: Inventarisiere jede Drittanbieter-Action
Starte mit einer Suche nach allen uses:-Einträgen unter .github/workflows/. Für die erste Sichtung reichen die GitHub-Suche, grep -R 'uses:' .github/workflows oder rg 'uses:' .github/workflows. Ordne jede Action einer Quelle zu: offizielle GitHub-Action wie actions/checkout, verifizierter Publisher, interne Action deiner Organisation oder unbekanntes Drittanbieter-Repository.
Bewerte danach den Laufzeitkontext. Eine Action in einem Job ohne Secrets und mit contents: read hat ein anderes Risiko als eine Action in einem Produktions-Deployment mit Cloud-Rolle. Dokumentiere mindestens die folgenden Felder.
| Feld | Beispiel | Prüffrage |
|---|---|---|
| Action-Name | tj-actions/changed-files | Wird die Action noch gepflegt? |
| Aktuelle Referenz | @v45.0.7, @v4, @main | Ist die Referenz ein vollständiger Commit-Hash? |
| Token-Rechte | contents: write | Braucht der Job wirklich Schreibrechte? |
| Secret-Zugriff | AWS_ROLE, NPM_TOKEN | Sieht die Action Secrets oder Deployment-Credentials? |
| Ersatzoption | Shell-Befehl, interne Action | Lässt sich die Funktion ohne externe Action abbilden? |
Schritt 2: Pinne Actions auf vollständige Commit-Hashes statt auf Tags
Tags wie @v4, Release-Tags und @main sind bewegliche Referenzen. Wenn ein Angreifer Zugriff auf das Action-Repository erhält, kann er Tags verschieben oder löschen. Ein vollständiger Commit-Hash zeigt auf ein konkretes Git-Objekt; GitHub beschreibt diese Form als unveränderliche Referenz für Actions.
# Vorher: beweglicher Tag
steps:
- uses: actions/checkout@v4
# Nachher: vollständiger Commit-Hash
steps:
- uses: actions/checkout@<full-commit-sha>Setze GitHub Actions SHA-Pinning zuerst bei Workflows mit Secrets, Deployment-Rechten, Paket-Veröffentlichungen und Release-Signaturen um. Wichtig: SHA-Pinning ersetzt keine Prüfung des Action-Codes. Bei jedem Update solltest du den neuen Commit anhand des Release-Diffs prüfen, die zugehörige Release-Notiz lesen und erst danach die SHA aktualisieren.
In Organisationen und Enterprises kannst du GitHub-Actions-Policies nutzen, um erlaubte Actions einzuschränken und vollständige Commit-SHAs für Actions zu erzwingen.
Schritt 3: Reduziere GITHUB_TOKEN-Permissions
Setze Standard-Permissions auf Repository- oder Organisationsebene auf read-only oder im Workflow auf permissions: {}. Vergib Schreibrechte nur in dem Job, der sie benötigt. Viele Workflows brauchen für Checkout, Tests und Linting nur contents: read. OIDC-Jobs brauchen zusätzlich id-token: write, aber kein pauschales contents: write und kein write-all.
name: deploy
on:
push:
branches: [main]
permissions: {}
jobs:
deploy-aws:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@<full-commit-sha>
- name: Configure AWS credentials through OIDC
uses: aws-actions/configure-aws-credentials@<full-commit-sha>
with:
role-to-assume: arn:aws:iam::123456789012:role/github-deploy-prod
aws-region: eu-central-1pull_request_target benötigt eine separate Prüfung. Dieses Event läuft im Kontext des Basis-Repositorys. Wenn der Job nicht vertrauenswürdigen Code aus dem Pull Request auscheckt und gleichzeitig Schreibrechte oder Secrets erhält, entsteht ein direkter Weg zur Exfiltration oder zur Manipulation von Releases. Nutze pull_request_target nur für Metadaten wie Labels oder Kommentare, nicht zum Bauen oder Ausführen des PR-Codes.
Schritt 4: Ersetze langlebige Cloud-Secrets durch OIDC
GitHub Actions OIDC ermöglicht Cloud-Deployments ohne statische Access Keys als GitHub-Secrets. Der Job fordert ein OpenID-Connect-Token von GitHub an. Der Cloud-Provider prüft Claims wie repository, ref, environment, workflow und sub. Erst danach stellt der Cloud-Provider kurzlebige Credentials für eine eng begrenzte Rolle aus.
- Für AWS richtest du den OIDC-Provider
token.actions.githubusercontent.commit der Audiencests.amazonaws.comein, beschränkstsubauf Repository, Branch oder Environment und erlaubst in der IAM-Rolle nur die benötigten Deploy-Aktionen. - Für Azure legst du eine Federated Credential an einer App Registration oder Managed Identity an und bindest Issuer, Subject und Audience an das gewünschte Repository und Environment.
- Für Google Cloud nutzt du Workload Identity Federation, definierst Attribute-Mappings für GitHub-Claims und erlaubst dem Service Account nur die erforderlichen Ressourcen.
Vergib id-token: write nur an Jobs, die Cloud-Federation nutzen. Ein Test-Job, der Unit-Tests ausführt, braucht kein OIDC-Token.
Schritt 5: Schütze Workflow-Änderungen mit Reviews und CODEOWNERS
Behandle .github/workflows/ wie sicherheitsrelevanten Infrastrukturcode. Eine bösartige Workflow-Änderung kann Secrets per HTTP hochladen, maskierte Werte in Teilstrings zerlegen, um Log-Masking zu umgehen, oder den Deployment-Pfad durch ein manipuliertes Artefakt ersetzen.
# .github/CODEOWNERS
.github/workflows/** @org/platform-team @org/security-teamKombiniere CODEOWNERS mit Branch-Protection-Regeln, Pull-Request-Reviews und verpflichtenden Status-Checks. Für Workflows mit Produktions-Deployments solltest du zusätzlich GitHub-Environments mit Required Reviewers verwenden, damit ein geänderter Job nicht automatisch in Produktion schreiben kann.
Schritt 6: Automatisiere Prüfungen mit Dependabot, Code Scanning und OpenSSF Scorecard
Dependabot kann veraltete GitHub-Actions-Referenzen erkennen, wenn sie auf Tags oder Versionsreihen zeigen. Bei vollständig gepinnten SHAs brauchst du zusätzlich einen Update-Prozess: neuen Release-Tag prüfen, zugehörigen Commit ermitteln, Diff lesen, SHA aktualisieren und die Änderung reviewen lassen.
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weeklyErgänze Secret Scanning für versehentlich committete Tokens sowie Code Scanning, actionlint oder OPA/Conftest-Regeln für riskante Muster wie pull_request_target mit Checkout von fremdem Code. OpenSSF Scorecard prüft unter anderem Pinned-Dependencies, Token-Permissions, Dangerous-Workflow und Script-Injection. Plane eine erneute Workflow-Prüfung nach größeren Dependency-Upgrades, Runner-Wechseln oder Cloud-Rollenänderungen ein.
Schritt 7: Segmentiere Self-Hosted-Runner oder nutze ephemere Runner
Self-Hosted-Runner werden zu kritischen Zielen, wenn sie nicht vertrauenswürdigen Code aus Pull Requests verarbeiten und gleichzeitig Zugriff auf interne Netze, Docker-Sockets, Build-Caches oder Cloud-Metadata-Endpunkte haben. Trenne Runner nach Vertrauensgrenze: öffentliche Pull Requests, interne Builds, Produktions-Deployments und privilegierte Infrastruktur-Jobs.
Nutze für sensible Jobs ephemere Runner, die nach genau einem Job verworfen werden. Dadurch bleiben Workspace-Daten, Build-Artefakte, temporäre Tokens und Tool-Caches nicht für den nächsten Lauf erhalten. Beschränke außerdem Egress-Verbindungen, Dateisystem-Mounts und den Zugriff auf Cloud-Metadata-Adressen wie 169.254.169.254; erlaube nur die benötigten Paket-Registries und Cloud-Endpunkte.
Abschluss-Checkliste: dein GitHub-Actions-Hardening-Sprint
Plane für die riskantesten Repositories einen 1- bis 2-tägigen Sprint. Beginne mit Deployment-Workflows, Release-Jobs und Repositories mit Secrets. Inventarisiere uses:-Einträge, priorisiere Jobs mit Secrets, ersetze Tags durch vollständige Commit-Hashes, reduziere GITHUB_TOKEN permissions, aktiviere OIDC und schütze Workflow-Dateien mit CODEOWNERS.
| Reifegrad | Kontrollen |
|---|---|
| Basis | Inventar, read-only Permissions, Dependabot für Actions, Secret Scanning. |
| Gehärtet | SHA-Pinning, OIDC statt Cloud-Secrets, CODEOWNERS, Branch Protection, Review-Pflicht für Environments. |
| Fortgeschritten | Ephemere Runner, Runner-Segmentierung, Egress-Regeln, OpenSSF Scorecard als Pflicht-Check. |
Du musst nicht alle Pipelines gleichzeitig umbauen. Starte mit Workflows, die Deployments ausführen oder Secrets lesen, und übertrage die gleichen Kontrollen danach auf Build- und Test-Jobs. Für interne Lernpfade kannst du die Themen trennen: Cloud-Federation in Amazon Web Services (AWS) Schulungen, Pipeline-Design in DevOps-Trainings, Secret-Handling in IT-Security-Schulungen und Reviews von Git-Änderungen in Git-Trainings.