- GitHub Actions nutzt in Workflow-Dateien die
uses:-Syntax mit einer Struktur zum Deklarieren und Ausführen von Paketabhängigkeiten, wodurch es faktisch wie ein Paketmanager funktioniert
- Es fehlen jedoch grundlegend Funktionen, die andere Paketmanager standardmäßig bieten, wie Lockfile, Integritäts-Hash, transitive Dependency-Pinning, Sichtbarkeit des Abhängigkeitsbaums usw.
- Nach Recherchen führen die meisten GitHub-Actions-Nutzer nicht verifizierten externen Code aus, und es wurden Code-Injection-Schwachstellen in tausenden Workflows gefunden
- GitHub hat einige Gegenmaßnahmen eingeführt (immutable Releases, SHA-Pin-Policy usw.), doch Probleme mit transitiven Abhängigkeiten und Reproduzierbarkeit sind weiterhin ungelöst
- Diese strukturellen Mängel wirken sich auf die gesamte Software-Lieferkettensicherheit aus und verbreiten sich auf andere CI-Systeme, die auf GitHub Actions basieren
Paketverwaltungsstruktur und Probleme von GitHub Actions
- Die Syntax
uses: actions/checkout@v4 ist eine Abhängigkeitsdeklaration, die GitHub auswertet, herunterlädt und ausführt
- Das entspricht dem üblichen Verhalten eines Paketmanagers, aber ohne Lockfile kann bei jedem Lauf eine andere Version ausgewählt werden
- Im Vergleich zu anderen Paketmanagern (npm, Cargo, NuGet usw.) fehlen Actions Lockfile, transitive Pinning-Funktionen, Integritätsprüfung, Sichtbarkeit des Abhängigkeitsbaums und eine Auflösungs-Spezifikation vollständig
- Der zentrale Punkt ist das Fehlen eines Lockfiles, wodurch sich die Abhängigkeitsauflösung von Ausführung zu Ausführung ändert und nichtdeterministische Builds entstehen
Sicherheitsergebnisse und Schwachstellen
- Laut einer USENIX-Security-Studie von 2022 führen 99,7 % der Repositories externe Actions von Drittentwicklern aus, 97 % von nicht verifizierten Herausgebern, und 18 % weisen fehlende Sicherheitsupdates auf
- In einer Folgestudie wurden in über 4.300 von 2,7 Millionen Workflows Code-Injection-Schwachstellen entdeckt
- GitHub Actions bietet zentrale Sicherheitsattribute von CI/CD wie admittance control, execution control, code control und Zugriffskontrolle auf Secrets nicht ausreichend
Zentrale technische Schwächen
- Variabler Versionsaspekt: Tags wie
@v4 können von Maintainer:innen mit einem neuen Commit erneut gesetzt werden, wodurch Code still verändert werden kann
- Mit einem Lockfile könnte dokumentiert werden, welcher SHA für dieses Tag aufgelöst wurde
- Intransparenz transitiver Abhängigkeiten: Actions, die innerhalb einer Composite Action aufgerufen werden, sind nicht einsehbar und nicht kontrollierbar
- Laut Studie enthalten 54 % der JavaScript-Actions Sicherheitslücken, wobei die meisten aus indirekten Abhängigkeiten stammen
- Beim Vorfall
tj-actions/changed-files führte ein Update transitiver Abhängigkeiten zu einem Secret-Leak-Angriff
- Fehlende Integritätsprüfung: npm oder Cargo speichern Hashes und validieren damit den Download, während Actions sich allein auf SHA-basierte Vertrauensannahmen verlässt
- Nicht reproduzierbare Wiederholung: GitHub gibt an, dass bei einem „force push“ auf eine Version die neueste Version gezogen wird, sodass dasselbe Workflow-Dokument unterschiedlichen Code ausführen kann
- Nicht sichtbarer Abhängigkeitsbaum: Funktionen wie
npm ls in npm oder cargo tree in Cargo fehlen, daher gibt es keine Möglichkeit, die gesamte Abhängigkeitsstruktur einzusehen
- Intransparente Auflösungsregeln: Die Abhängigkeitsauflösung von Actions ist nicht dokumentiert und der Code in
ActionManager.cs enthält nur eine einfache rekursive Download-Logik
Zusätzliche strukturelle Grenzen
- Fehlendes zentrales Registry: Actions befinden sich in Git-Repositories und verfügen über keinen zentralen Mechanismus für Sicherheits-Scans, Malware-Erkennung oder Typosquatting-Schutz
- Gemeinsame Umgebung: Mehrere Actions ändern dasselbe
$PATH, sodass das Ergebnis je nach Ausführungsreihenfolge variiert
- Keine Offline-Ausführung: Bei jedem Lauf muss von GitHub heruntergeladen werden; ohne Netzwerk ist eine Ausführung nicht möglich
- Namespace-Schwachstellen: Der GitHub-Benutzername ist zugleich der Namespace und damit anfällig für Kontoübernahmen und Tippfehlerangriffe
- Mit Lockfile und Integritäts-Hashes ließen sich Codeänderungen durch Buildfehler erkennen
Entwurfsgrundlage und Auswirkungen
- Der Actions-Runner wurde ursprünglich auf Azure DevOps aufgebaut und für eine intern vertrauensvolle Umgebung konzipiert
- Als GitHub dies zu einem öffentlichen Marktplatz ausweitete, wurde das Vertrauensmodell nicht neu entworfen
- Dadurch wurden Basisfunktionen wie Lockfile, Integritätsprüfung, transitive Pinning-Mechanismen, Sichtbarkeit von Abhängigkeiten weggelassen
- Mit der Ausbreitung der OIDC-basierten automatisierten Paketverteilung wirkt sich der Sicherheitsmangel von Actions auf die gesamte Supply-Chain-Sicherheit von Paketregistries aus
- Während GitLab CI das Schlüsselwort
integrity für Hash-Verifikation eingeführt hat, schloss GitHub einen vergleichbaren Antrag mit dem Vermerk „No plans“ ab
- GitHub-kompatible CI-Systeme wie Forgejo Actions müssen dieselbe Struktur beibehalten, wodurch sich diese Schwächen auf das gesamte Ökosystem ausdehnen
Verbesserungsvorschläge und aktueller Stand
- Die Community hat in Issue #2195 Lockfile-Unterstützung gefordert, doch GitHub schloss es 2022 mit dem Hinweis „No plans“
- Eine Studie von Palo Alto zeigte, dass ein reines SHA-Pinning keine transitive Abhängigkeit absichert
- Einige Teams kompensieren dies mit Dependabot-Updates, eigenem Repository-Vendoring und dem Security-Scanner zizmor
- Die grundlegende Abhilfe wäre die Einführung eines Lockfiles, das SHA- und Integritäts-Hashes für alle Actions und deren transitive Abhängigkeiten speichert
- Solange GitHub dies nicht übernimmt, ist eine belastbare Sicherung der CI/CD-Lieferkette nicht möglich
Noch keine Kommentare.