FlawOpen

flawopen.com/GitHub-Actions-Sicherheit/Workflow-Script-Injection

Wie entsteht Script-Injection in GitHub Actions, und wie lässt sie sich verhindern?

Hohe Auswirkung bei erhöhten Rechten CWE-78 CI/CD-Workflow-Sicherheit
Einfach erklärt

Ein Workflow kann Daten in Shell-Syntax verwandeln, wenn er einen Issue-Titel oder ein Pull-Request-Feld vor dem Bash-Start in das Script einsetzt. Wie ein Drucker, der einen Namen für einen Befehl hält. Übergeben Sie den Wert per Umgebungsvariable und quotieren Sie die Expansion, wenn Sie ihn als Daten verwenden. Bash erhält ihn so getrennt vom Script. Die Auswirkung hängt weiterhin von Token, Secrets, Runner und Ereignis ab.

Nicht vertrauenswürdiger KontextGitHub-Ereignisfelder wie Titel, Texte, Branch-Namen, Labels und Commit-Nachrichten. Als fremdkontrollierte Zeichenketten behandeln.
AusdrucksersetzungGitHub wertet ${{ ... }} vor dem Shell-Start aus. In run: kann Eingabe so in den Script-Quelltext gelangen.
Übergabe per Umgebungenv: übergibt Werte als Prozessdaten. Shell-Expansion quotieren; eval und dynamische Scripts vermeiden.
BerechtigungsgrenzeEreignis und Workflow bestimmen Token-Rechte, Secrets und Runner-Zugriff. Die Auswirkung hängt von den Ressourcen des Jobs ab.

Ursache: Daten gelangen vor der Shell-Analyse ins Script

GitHub expandiert Ausdrücke, bevor die Shell eines run-Schritts startet. Wird ein nicht vertrauenswürdiger Titel direkt eingesetzt, können seine Zeichen das Shell-Programm verändern. Ein Wert aus env: bleibt vom Scripttext getrennt; quotiert bleibt er bei normalen Befehlen ein Argument. Das macht eine spätere Verwendung mit eval, einem anderen Interpreter oder einem Argumente als Code deutenden Tool nicht sicher. GitHub stuft Ereignisfelder als potenziell angreiferkontrollierte Eingaben ein.

.github/workflows/triage.yml (Unsichere Interpolation)Unsicher
# UNSICHER: Ereignisdaten werden Teil des erzeugten Shell-Scripts
name: Issue Triage
on:
  issues:
    types: [opened]

permissions:
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Print issue title
        run: |
          printf 'Title: %s\n' "${{ github.event.issue.title }}"
.github/workflows/triage.yml (Getrennte Daten)Gehärtet
# Sicherer: Ereigniswert über die Umgebung übergeben
name: Issue Triage
on:
  issues:
    types: [opened]

permissions:
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Print issue title
        env:
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: |
          printf 'Title: %s\n' "$ISSUE_TITLE"

Angriffspfad im Überblick

Step 1

Benutzer kontrolliert ein Ereignisfeld

Etwa ein öffentlicher Issue- oder Pull-Request-Titel oder ein Branch-Name wird zur Workflow-Eingabe.

Step 2

Workflow setzt es in Shell-Quelltext ein

Ein Ausdruck ${{ github.event... }} in run: wird ausgewertet, bevor Bash das Script parst.

Step 3

Shell interpretiert das geänderte Programm

Ändert der Wert die Syntax, laufen Befehle mit der Prozessidentität des Jobs. Als quotiertes Argument bleibt der Wert dagegen Daten.

Step 4

Job-Rechte bestimmen die Auswirkung

Ein kompromittierter Job erreicht nur Ressourcen dieses Laufs: effektive GITHUB_TOKEN-Rechte, Secrets und Runner. Issue-Ereignisse und pull_request_target sorgfältig prüfen.

Härtungs-Checkliste

Primärquellen

Weitere Sicherheitsthemen und Analysen entdecken:Vollständiges Sicherheitsverzeichnis →
Siehe auch Cosign GHSA-fx35-mq7g-6g98: Bundle-Bypass Dependency Confusion: Risiken und Schutzmaßnahmen Docker-Socket-Offenlegung: Risiken und Schutz