Design wechseln

GitHub Actions Secrets verwalten: Von Leckrisiken zu OIDC ohne statische Credentials

An einem Wochenende im März 2025 verschickte das GitHub-Sicherheitsteam eine dringende E-Mail an die Besitzer von über 23.000 Repositories.

Ihre Secrets könnten bereits geleakt sein.

Der Übeltäter war die Action tj-actions/changed-files – ein weit verbreitetes Tool, das Angreifer kompromittiert hatten, um still alle Umgebungsvariablen und Secrets aus Workflows abzugreifen. Vielleicht denken Sie gerade: Mein Projekt nutzt diese Action auch – bin ich betroffen?

Dieser Vorfall rückte ein oft unterschätztes Thema ins Rampenlicht: Wie sollte man Secrets in GitHub Actions eigentlich verwalten?

In diesem Artikel geht es um drei Dinge: welche der drei Architekturebenen passt, wie Sie die 8 Sicherheitsregeln einhalten und wie OIDC Ihnen den Albtraum statischer Credential-Leaks erspart.

1. Die Drei-Ebenen-Architektur für GitHub Actions Secrets

GitHub bietet drei Ebenen zum Speichern von Secrets: Repository, Environment und Organization. Welche wählen Sie? Die Antwort hängt von Ihrem Szenario ab.

Repository Secrets: erste Wahl für Einzelprojekte

Das ist die einfachste Ebene. Secrets liegen auf Repository-Ebene; alle Workflows können darauf zugreifen. Für persönliche Projekte, Monorepos ohne Multi-Environment-Deployment reicht das völlig aus.

Der einzige Nachteil: Sie können nicht zwischen staging und production unterscheiden, wenn beide denselben Secret-Namen brauchen. Haben Sie z. B. ein DATABASE_URL mit unterschiedlichen Werten pro Umgebung, brauchen Sie Environment Secrets.

Environment Secrets: unverzichtbar für Multi-Environment-Deployments

Environment Secrets isolieren Secrets nach Umgebung und unterstützen Freigabe-Workflows. In den Repository-Einstellungen legen Sie z. B. staging und production an und konfigurieren je eigene Secrets.

Ein zentrales Merkmal: Nur Jobs, die die jeweilige Environment referenzieren, greifen auf deren Secrets zu. So wird die Sicherheitsgrenze klarer.

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging  # staging-Environment referenzieren
    steps:
      - run: echo "Deploying to staging..."
      - env:
          API_KEY: ${{ secrets.API_KEY }}  # Secret aus staging-Environment

  deploy-production:
    runs-on: ubuntu-latest
    environment: production  # production-Environment (Freigabe möglich)
    steps:
      - run: echo "Deploying to production..."
      - env:
          API_KEY: ${{ secrets.API_KEY }}  # Secret aus production-Environment

In dieser Konfiguration sieht deploy-staging nur Secrets aus staging, deploy-production nur aus production. Beide stören sich nicht gegenseitig.

Environments unterstützen außerdem Schutzregeln – z. B. kann production so konfiguriert werden, dass ein manueller Freigabeschritt Pflicht ist. Das hilft im Team besonders.

Organization Secrets: teamweit teilen, zentral verwalten

Hat Ihr Team Dutzende Repositories und überall dieselben AWS_ACCESS_KEY-Werte? Copy-Paste zigfach, bei Updates wieder zigfach ändern – das frustriert schnell.

Organization Secrets lösen genau das. Einmal auf Organisationsebene konfigurieren, in allen Repositories nutzen. Sie steuern den Zugriff: alle Repositories oder eine definierte Liste.

# Im Repository-Workflow identisch zu Repository Secrets
steps:
  - env:
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Wie wählen Sie?

Kurz gesagt:

SzenarioEmpfohlene Ebene
Einzelprojekt, eine UmgebungRepository Secrets
Multi-Environment (staging/production)Environment Secrets
Team mit vielen Repos, geteilte CredentialsOrganization Secrets

Aus eigener Erfahrung: Viele Projekte starten mit Repository Secrets und wechseln erst bei Multi-Environment-Bedarf zu Environment Secrets. Die Migration ist nicht aufwendig – trotzdem lohnt frühe Planung.

2. Sicherheits-Best Practices für Secrets – 8 Regeln

Oben ging es um Speicherung, hier um Nutzung. Acht Regeln aus der Praxis – jede mit einer Lektion dahinter.

1. Einheitliche Benennung

Großbuchstaben und Unterstriche, z. B. AWS_ACCESS_KEY_ID. Kein CamelCase, keine Kleinbuchstaben. So erkennen Sie Secrets auf den ersten Blick und verwechseln sie nicht mit normalen Variablen.

2. Kein JSON als einzelnes Secret

Ein klassischer Fehler: die gesamte Konfiguration in ein Secret packen:

{"api_key": "xxx", "db_url": "yyy", "token": "zzz"}

Dann in der Workflow-Datei per fromJson parsen. Problem: Leakt dieses Secret, sind alle sensiblen Werte gleichzeitig offen. Besser: jeden Wert als eigenes Secret speichern.

3. Explizit übergeben, nicht inline

# Falsch ❌
- run: my-cli --token ${{ secrets.MY_TOKEN }}

# Richtig ✅
- env:
    MY_TOKEN: ${{ secrets.MY_TOKEN }}
  run: my-cli --token $MY_TOKEN

Warum? GitGuardian zeigt: Kommandozeilenargumente können andere Prozesse auf demselben System per ps x -w lesen. Umgebungsvariablen sind deutlich sicherer.

4. Regelmäßige Rotation

Alle 30 bis 90 Tage wechseln. Rotation ist lästig – aber im Vergleich zur Schadensbegrenzung nach einem Leak lohnt sich der Aufwand. Das Blacksmith-Team empfiehlt: Mit Cloud-Diensten (AWS/GCP) und OIDC können Sie Rotation ganz überspringen.

5. Actions per SHA fixieren

Erste Verteidigungslinie gegen Supply-Chain-Angriffe.

# Falsch ❌
- uses: tj-actions/changed-files@v45

# Richtig ✅
- uses: tj-actions/changed-files@b827595e0a7e97537d7c7a2f458b5a8e6d5c8e39

Commit-SHA statt Versions-Tag. Tags können Angreifer umleiten; SHAs sind unveränderlich.

6. GITHUB_TOKEN mit minimalen Rechten

GitHub stellt jedem Workflow automatisch ein GITHUB_TOKEN bereit. Standardrechte sind oft zu hoch – Schreibzugriff auf Code, Issues bearbeiten. Setzen Sie in Workflow oder Repository-Einstellungen lieber read-only:

permissions:
  contents: read

7. Prüfen, ob Secrets in Logs maskiert werden

GitHub ersetzt ${{ secrets.XXX }} in Logs durch ***. Schreiben Sie aber:

- run: echo "Token is $MY_TOKEN"

erscheint der echte Token-Wert im Log. Testen Sie Workflows und prüfen Sie auf unbeabsichtigte Offenlegung.

8. Abgeleitete sensible Werte registrieren

Erzeugt Ihr Workflow aus einem Secret neue sensible Werte (z. B. JWT aus API-Key), registrieren Sie auch diese als Secret – nicht nur im Speicher weitergeben.


Diese acht Regeln sind keine Theorie. Nach dem tj-actions-Vorfall prüfte StepSecurity Tausende öffentlicher Repositories – ein erheblicher Anteil verstieß gegen sie. Beheben ist machbar, braucht aber systematische Prüfung.

3. OIDC – Cloud-Deployment ohne statische Secrets

Bei Regel 4 stand Rotation. Ehrlich gesagt: Rotation nervt – AWS-Konsole, GitHub Secrets, Team informieren.

OIDC (OpenID Connect) bietet einen Ausweg: Gar keine Secrets speichern.

Wie funktioniert OIDC?

Klassisch: IAM-Benutzer in AWS, Access Key erzeugen, Key in GitHub Secrets ablegen. Der Workflow nutzt diesen statischen Key für AWS-Ressourcen.

Mit OIDC: GitHub fungiert als Identity Provider und beweist gegenüber AWS: „Dieser Workflow stammt aus dem Repository eastondev/my-repo.“ AWS prüft und stellt ein kurzlebiges JWT aus (Gültigkeit Minuten bis Stunden). Der Workflow arbeitet damit und das Token verfällt danach automatisch.

Keine Langzeit-Credentials, keine Rotation, kein Leckrisiko statischer Keys.

AWS-OIDC-Konfigurationsbeispiel

Zwei Teile: Trust Relationship in AWS, Token-Anfrage in GitHub.

AWS-Seite (Konsolen-Schritte):

  1. IAM Identity Provider anlegen, URL: https://token.actions.githubusercontent.com
  2. IAM Role mit Trust Policy, die auf Ihr Repository beschränkt:
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "arn:aws:iam::123456789:oidc-provider/token.actions.githubusercontent.com"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
        "token.actions.githubusercontent.com:sub": "repo:eastondev/my-repo:ref:refs/heads/main"
      }
    }
  }]
}

Bedeutung: Nur der main-Branch von eastondev/my-repo darf diese Role annehmen.

GitHub-Seite (Workflow):

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # Pflicht: OIDC-Token anfordern
      contents: read
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
          aws-region: us-east-1
      - run: aws s3 sync ./dist s3://my-bucket

Kein secrets.AWS_ACCESS_KEY – Authentifizierung direkt über die Role.

GCP und Azure

Alle drei großen Clouds unterstützen OIDC; die Konfiguration ist ähnlich:

CloudGitHub ActionStichwort in der Doku
AWSaws-actions/configure-aws-credentialsOIDC federation
GCPgoogle-github-actions/authWorkload Identity Federation
Azureazure/loginFederated Identity Credentials

Ein unerwarteter Vorteil von OIDC

Tests von johal.in zeigen: OIDC senkt die Authentifizierungslatenz gegenüber klassischen Secrets um etwa 87 %. Grund: kein Abruf über die GitHub-Secrets-API – lokales JWT gegen temporäres Token tauschen.

In der Praxis ist OIDC meine erste Wahl fürs Cloud-Deployment. Die Einrichtung ist etwas aufwendiger – danach ist sie wartungsarm.

4. Schutz vor Supply-Chain-Angriffen – Rückblick auf tj-actions

Zurück zum Einstieg: tj-actions/changed-files. Wie passierte es? Was lernen wir?

Ablauf

Im März 2025 erlangten Angreifer Maintainer-Rechte im tj-actions-Repository (Ursache noch untersucht – Credential-Leak oder Account-Kompromittierung). In Version v45 fügten sie ein Skript ein, das bei Workflow-Lauf alle Umgebungsvariablen und Secrets auslas und an einen kontrollierten Server sendete.

Semgrep: Alle Workflows mit tj-actions/changed-files@v45 waren betroffen – unabhängig von GitHub Secrets oder OIDC. Hat die Action Zugriff auf Umgebungsvariablen, konnte sie diese abgreifen.

Unit42 (Palo Alto Networks): Über 23.000 Repositories nutzten die Action, teils Forks bekannter Projekte.

Lehren

Der Vorfall zeigte:

  1. Action-Versions-Tags sind nicht vertrauenswürdig – Angreifer können Tags auf bösartige Commits zeigen lassen
  2. Drittanbieter-Actions sehen Ihre Secrets – bei Kompromittierung sind alle betroffen
  3. Historische Run-Logs können sensible Daten enthalten – auch nach Fix bleiben Spuren möglich

Ihre Checkliste

Haben Sie tj-actions/changed-files genutzt, prüfen Sie:

□ Workflow-Logs auf Secrets in der Ausgabe
□ Rotation aller möglicherweise exponierter Secrets (API Keys, Tokens)
□ Action auf Commit-SHA statt Versions-Tag fixieren
□ Maintainer-Herkunft anderer Drittanbieter-Actions prüfen
□ Dependabot oder Renovate für Action-Versionen erwägen

Für unbetroffene Projekte ist SHA-Fixierung die wichtigste Maßnahme. SHAs sind unhandlicher als Tags – aber der einzige Schutz vor Tag-Manipulation.

GitHubs Sicherheits-Roadmap 2026 nennt eine wichtige Richtung: Trennung von Code-Contributions und Credential-Verwaltung. Feinere Zugriffskontrollen könnten Drittanbieter-Actions nur nötige Secrets geben – gut, aber bis dahin bleiben wir selbst verantwortlich.

Fazit

GitHub Actions Secrets sind kein komplexes Technikproblem, sondern eine dauerhafte Sicherheitsdisziplin. Kurz zusammengefasst:

Architektur: Repository Secrets für Einzelprojekte, Environment Secrets für Multi-Environment, Organization Secrets für teamweites Teilen.

Sicherheitsregeln: SHA-Fixierung, explizite Übergabe, regelmäßige Rotation – diese drei zuerst.

Cloud-Authentifizierung: OIDC bevorzugen – keine statischen Secrets, keine Rotationslast.

Supply Chain: Secrets-Zugriff Drittanbieter-Actions begrenzen, Maintainer prüfen.

Nach tj-actions mache ich persönlich: alle Actions per SHA, Cloud-Deployments per OIDC, monatliches Secrets-Audit. Der Aufbau dauerte etwa zwei Wochen; danach ist der Pflegeaufwand gering.

Wenn Sie noch nicht geprüft haben: gehen Sie heute die Checkliste durch. Vorbeugen kostet weniger als nachträgliche Schadensbegrenzung.

GitHub Actions OIDC-Deployment ohne statische Secrets einrichten

OIDC-Authentifizierung für AWS konfigurieren und sicher deployen ohne statische Credentials

⏱️ Estimated time: 30 min

  1. 1

    Step 1: IAM Identity Provider anlegen

    In der AWS-IAM-Konsole einen Identity Provider erstellen:

    • Provider URL: https://token.actions.githubusercontent.com
    • Audience: sts.amazonaws.com
    • Generierte Provider-ARN notieren
  2. 2

    Step 2: IAM Role mit Trust Policy anlegen

    IAM Role erstellen, Trust Policy auf Ihr GitHub-Repository beschränken:

    ```json
    {
    "Version": "2012-10-17",
    "Statement": [{
    "Effect": "Allow",
    "Principal": {
    "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
    "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
    "token.actions.githubusercontent.com:sub": "repo:OWNER/REPO:ref:refs/heads/main"
    }
    }
    }]
    }
    ```

    • ACCOUNT_ID durch Ihre AWS-Konto-ID ersetzen
    • OWNER/REPO durch Ihr GitHub-Repository ersetzen
    • :ref:refs/heads/main entfernen, um alle Branches zu erlauben
  3. 3

    Step 3: Workflow für OIDC konfigurieren

    OIDC-Token im GitHub Actions Workflow anfordern:

    ```yaml
    jobs:
    deploy:
    runs-on: ubuntu-latest
    permissions:
    id-token: write # Pflicht: OIDC-Token anfordern
    contents: read
    steps:
    - uses: aws-actions/configure-aws-credentials@v4
    with:
    role-to-assume: arn:aws:iam::ACCOUNT_ID:role/GitHubActionsRole
    aws-region: us-east-1
    - run: aws s3 sync ./dist s3://my-bucket
    ```

    • id-token: write ist eine Pflicht-Berechtigung
    • Kein secrets.AWS_ACCESS_KEY_ID nötig
  4. 4

    Step 4: Testen und validieren

    Workflow ausführen und OIDC prüfen:

    • Workflow-Log: Authentifizierung erfolgreich
    • role-to-assume korrekt
    • AWS-Zugriff ohne statische Credentials
    • Zieloperation testen (z. B. S3-Sync, ECR-Push)

FAQ

Was ist der Unterschied zwischen Repository Secrets und Environment Secrets?
Repository Secrets liegen auf Repository-Ebene; alle Workflows können darauf zugreifen. Environment Secrets sind pro Environment isoliert – nur Jobs mit Environment-Referenz sehen die jeweiligen Secrets, inklusive Freigabe-Workflows. Für Multi-Environment-Deployments empfehlen sich Environment Secrets.
Wie nutze ich Secrets sicher in Workflows?
Drei Prinzipien:

• Explizite Übergabe: per env-Feld injizieren, nicht inline ${{ secrets.XXX }}
• Least Privilege: nur an benötigte Steps, bei GITHUB_TOKEN permissions: contents: read setzen
• Regelmäßige Rotation: alle 30–90 Tage; mit OIDC für Cloud-Deployment Rotation entfällt
Was ist OIDC? Warum ist es sicherer als klassische Secrets?
OIDC (OpenID Connect) lässt GitHub als Identity Provider die Workflow-Identität gegenüber der Cloud nachweisen; die Cloud stellt kurzlebige JWT-Tokens aus. Vorteile: keine statischen Credentials, keine Rotation, kein Leckrisiko. Authentifizierungslatenz etwa 87 % niedriger als bei klassischen Secrets.
Wie schütze ich mich vor Supply-Chain-Angriffen (z. B. tj-actions)?
Kernmaßnahmen:

• Actions auf Commit-SHA fixieren, keine Versions-Tags
• Secrets nur vertrauenswürdigen Actions übergeben
• Maintainer-Herkunft Drittanbieter-Actions prüfen
• Dependabot oder Renovate für Action-Updates nutzen
Können Secrets in Logs durchsickern?
GitHub ersetzt ${{ secrets.XXX }} in Logs durch ***. Nutzen Sie die Variable direkt (z. B. echo ${MY_TOKEN}), erscheint der echte Wert. Workflow-Logs testen und auf unbeabsichtigte Offenlegung prüfen.
Wann eignen sich Organization Secrets?
Bei vielen Repositories mit geteilten Credentials. Einmal auf Organisationsebene konfigurieren, teamweit nutzen. Zugriff: alle Repositories oder eine Auswahlliste. Beispiel: gemeinsamer AWS_ACCESS_KEY über mehrere Projekte – ohne Wiederholung in jedem Repository.

7 Min. Lesezeit · Veröffentlicht am: 18. Apr. 2026 · Aktualisiert am: 9. Juli 2026

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog