Text size
Ausprobiert & getestet7 Min. Lesezeit

GitHub-Aktionen nach echten Angriffen sperren

Eine kompromittierte Aktion ließ Geheimnisse aus Tausenden von Repos durchsickern. Was ich in meinem verändert habe.

Locking down GitHub Actions after real attacks
KI-generierte Illustration

Lange Zeit habe ich GitHub Actions Workflows wie Sanitärtechnik behandelt. Kopieren Sie einen Workflow aus einem README, fügen Sie hinzu uses: some-org/some-action@v3Und weitermachen. Die meisten von uns haben es getan.

Im März 2025 wird die tj-actions/changed-files Action wurde gehackt. Die Angreifer haben die Versionen verändert, um auf einen bösartigen Code zu zeigen, der CI-Geheimnisse in die Build-Logs durchsickerte. Tausende von Repos haben es benutzt. Viele hatten öffentliche Protokolle. Es war ein Weckruf: Unsere Pipelines laufen mit Drittanbieter-Code mit Zugriff auf unsere vertraulichsten Anmeldeinformationen, und wir denken selten darüber nach.

Hier ist, was ich geändert habe, und was ich jedem empfehlen würde, der Aktionen verwendet.

Was passiert ist, ist einfach

Wenn du schreibst uses: tj-actions/changed-files@v45, v45 ist ein Git-Tag. Die Marken können verschoben werden. Wenn ein Angreifer Schreibzugriff auf das Repository der Aktion erhält, kann er vorhandene Tags auf einen bösartigen Commit richten. Jeder Workflow, der dieses Tag verwendet, führt den neuen Code beim nächsten Lauf aus, ohne dass sich etwas in Ihrem Repository ändert.

Die Untersuchung zeigte später, dass der Hacker selbst mit einer anderen kompromittierten Aktion verbunden war. Die Lieferkette greift die Lieferketten an.

Ihre Pipeline ist nur so vertrauenswürdig wie die am wenigsten vertrauenswerte Aktion, die sie durchführt.

1. Die Aktionen an eine vollständige SHA-Kommitte anheften

Anstelle eines Tags, verweisen Sie auf den genauen Commit:

# Before
- uses: actions/checkout@v4

# After
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

Ein SHA-Kommando kann nicht verschoben werden. Die Version als Kommentar behalten, so dass Menschen es lesen können, und lassen Dependabot oder Erneuern Sie können die SHA (und den Kommentar) durch eine normale Pull-Anfrage aktualisieren, wenn eine neue Version veröffentlicht wird.

GitHub ermöglicht es Organisationen auch, SHA-Pinning in ihrer erlaubten Aktionsrichtlinie durchzusetzen, so dass nicht-gepinte Aktionen fehlschlagen.

2. Die Beschränken des GITHUB_TOKEN

Jeder Workflow erhält eine automatische GITHUB_TOKEN- Ich weiß . Die Standardberechtigungen hängen von Ihren Einstellungen ab, und in älteren Repositories sind sie oft viel zu breit.

Die Organisation oder das Repository als Standard-System auf nur Lesbar festlegen und nur das zugebe, was jeder Workflow benötigt:

permissions:
  contents: read

jobs:
  release:
    permissions:
      contents: write   # only this job can push tags

Ein durchgesickertes Lesetoken ist ein viel kleines Problem als ein durchgesickeres Schreibtoken.

3. Die Verwenden Sie keine Cloud-Keys mehr

Die Geheimnisse, die bei diesen Angriffen durchgesickert sind, waren oft Cloud-Zugangsschlüssel, die gültig sind, bis jemand sie wechselt. Sie ersetzen OIDC: der Workflow fordert ein kurzlebiges Token von GitHub an, und Ihr Cloud-Provider tauscht es gegen temporäre Anmeldeinformationen aus, aber nur für das spezifische Repository und den Branch, den Sie zulassen.

permissions:
  id-token: write
  contents: read

steps:
  - uses: aws-actions/configure-aws-credentials@<sha> # v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/deploy-shop
      aws-region: eu-central-1

AWS, Azure, Google Cloud, HashiCorp Vault und viele andere unterstützen das. Kein Geheimnis zu stehlen, und das Token läuft in Minuten ab.

4. Die Vorsicht bei gefährlichen Auslösern

pull_request_target und workflow_run Sie haben Zugang zu Geheimnissen, sogar für Anfragen von Gabeln. Kombiniert mit der Überprüfung des nicht vertrauenswürdigen Codes aus der Pull-Anfrage, sind sie eine klassische Möglichkeit für Angreifer, Geheimnisse zu stehlen. Vermeide sie, es sei denn, du verstehst wirklich das Risiko.

Achten Sie auch auf Schriftinjektion: mit nicht vertrauenswürdigen Eingaben wie einem Pull-Request-Titel direkt in einem run: Schritt.

# Dangerous: the title can contain shell commands
- run: echo "${{ github.event.pull_request.title }}"

# Safer: pass it through an environment variable
- env:
    TITLE: ${{ github.event.pull_request.title }}
  run: echo "$TITLE"

5. Die Beschränkung der Aktionen

In Organisations-Einstellungen dürfen nur:

  • Aktionen, die von GitHub erstellt wurden
  • Maßnahmen der überprüften Hersteller
  • Eine spezifische Liste der Aktionen, die Sie überprüft haben

Weniger Aktionen durch Dritte bedeuten weniger Dinge, die kompromittiert werden können. Für einfache Aufgaben sind ein paar Linien der Schale oft sicherer als eine Aktion.

6. Die Verwenden Sie Tools, die Ihre Arbeitsabläufe überprüfen

  • Zimmers: ein statisches Analyse-Tool für GitHub-Aktionen, das nicht feststehende Aktionen, Injektionsrisiken, gefährliche Auslöser und übermäßige Berechtigungen findet.
  • OpenSSF-Scorecard: Bewertet die Sicherheitspraktiken Ihres Repositoriums, einschließlich der Workflowhygiene.
  • StepSecurity Harden-Runner: überwacht und kann den Netzwerkzugang von Ihren Runnern einschränken, was viele Exfiltrationsversuche blockiert hätte.
  • Dependabot / Erneuerung für die Aktualisierung der festgelegten Aktionen.

Fügen Sie Zizmor zu Ihrem Informanten hinzu und reparieren Sie, was er findet. Es ist ein Augenöffner.

7. Sieben. Schützen Sie die Läufer .

  • Ich bevorzuge GitHub-hosted oder kurzlebige selbst gehostete Läufer (ein frisches VM oder Container pro Arbeitsplatz). Durchhaltende, selbst gehostete Läufer können durch einen bösartigen Job vergiftet und den nächsten beeinflussen.
  • Verwenden Sie niemals selbst gehostete Runner für öffentliche Repositories, in denen jeder eine Pull-Anfrage öffnen kann.

Also, wo fange ich an?

Wenn Sie nur drei Dinge in dieser Woche tun: Setzen Sie das Standard-Token auf nur-lesen, schließen Sie Ihre Drittanbieteraktionen an SHAs mit dem Update von Renovate an und ersetzen Sie einen langlebigen Cloud-Schlüssel durch OIDC. Dann laufen Sie mit Zizmor durch und arbeiten Sie die Liste durch.

Meine Meinung: CI-Pipelines halten den Schlüssel zu allem. Behandeln Sie alle uses: Die Linie ist wie eine Abhängigkeit, denn genau das ist sie.

Desly