- Ein bösartiges npm-Paket von Shai-Hulud 2.0 infizierte den Rechner eines Entwicklers und übernahm den Zugriff auf die GitHub-Organisation von Trigger.dev
- Die Infektion begann, als der Entwickler
pnpm install ausführte und dabei das preinstall-Skript des Schadpakets gestartet wurde; zum Diebstahl von Zugangsdaten wurde das Tool TruffleHog verwendet
- Die Angreifer klonten 669 Repositories innerhalb von 17 Stunden und versuchten anschließend innerhalb von 10 Minuten, 199 Branches per Force-Push zu überschreiben und 42 PRs zu schließen
- Pakete und Produktionssysteme wurden nicht kompromittiert; der Angriff wurde innerhalb von 4 Minuten nach der Erkennung blockiert
- Nach dem Vorfall wurde die Sicherheitsarchitektur ausgebaut, unter anderem durch das Deaktivieren von npm-Skripten, ein Upgrade auf pnpm 10, OIDC-basierte npm-Deployments und flächendeckenden Branch-Schutz
Überblick über den Angriff
- Am 25. November 2025 wurden während interner Debugging-Arbeiten in Slack ungewöhnliche Aktivitäten festgestellt: In mehreren Repositories tauchten „init“-Commits im Namen von Linus Torvalds auf
- Die Untersuchung ergab, dass der Supply-Chain-Wurm Shai-Hulud 2.0 den Rechner eines Entwicklers infiziert und GitHub-Zugangsdaten gestohlen hatte
- Berichten zufolge infizierte dieser Wurm mehr als 500 npm-Pakete und wirkte sich auf über 25.000 Repositories aus
- Die offiziellen npm-Pakete von Trigger.dev (
@trigger.dev/*, CLI) waren nicht infiziert
Zeitlicher Ablauf des Angriffs
-
- November, 04:11 UTC: Verteilung des bösartigen Pakets beginnt
- 20:27 UTC: Rechner eines Entwicklers in Deutschland infiziert
- 22:36 UTC: Erster Zugriff der Angreifer und Beginn des massenhaften Klonens von Repositories
- 15:27–15:37 UTC (25. November): Zehnminütiger destruktiver Angriff
- 15:32 UTC: Auffälligkeit erkannt und Zugriff innerhalb von 4 Minuten blockiert
- 22:35 UTC: Wiederherstellung aller Branches abgeschlossen
Infektionsablauf
- Als der Entwickler
pnpm install ausführte, wurde das preinstall-Skript des bösartigen Pakets gestartet, lud TruffleHog herunter und führte es aus
- TruffleHog scannte GitHub-Tokens, AWS-Zugangsdaten, npm-Tokens, Umgebungsvariablen und weitere Informationen und leitete sie nach außen weiter
- Auf dem infizierten Rechner wurden das Verzeichnis
.trufflehog-cache und zugehörige Dateien gefunden
- Das auslösende Paket wurde gelöscht und konnte daher nicht mehr zurückverfolgt werden
Aktivitäten der Angreifer
- Nach der Infektion liefen 17 Stunden lang Aufklärungsaktivitäten
- Über Infrastruktur in den USA und Indien wurden 669 Repositories geklont
- Die Entwickleraktivität wurde überwacht und der Zugriff über GitHub-Tokens aufrechterhalten
- Es wurde ein Repository mit dem Namen „Sha1-Hulud: The Second Coming“ erstellt, das vermutlich zum Speichern von Zugangsdaten diente
- Danach folgten 10 Minuten destruktiver Aktionen
- In 16 Repositories wurde versucht, 199 Branches per Force-Push zu überschreiben
- 42 PRs wurden geschlossen; einige Versuche wurden durch Branch-Schutzregeln blockiert
- Alle Commits erschienen im Format „Linus Torvalds <email> / init“
Erkennung und Reaktion
- Die Auffälligkeiten wurden in Echtzeit über Slack-Benachrichtigungen erkannt
- Innerhalb von 4 Minuten wurde der GitHub-Zugriff des kompromittierten Kontos gesperrt; anschließend wurden Zugriffe auf alle Dienste wie AWS, Vercel und Cloudflare entzogen
- Die Analyse der AWS-CloudTrail-Logs ergab, dass nur schreibgeschützte API-Aufrufe erfolgt waren; es gab keinen Zugriff auf Produktionsdaten
- AWS erkannte unabhängig davon verdächtige Aktivitäten im Zusammenhang mit Shai-Hulud und verschickte eine Warnung
Schaden und Wiederherstellung
- 669 geklonte Repositories, 199 Branches mit Force-Push, 42 geschlossene PRs
- Die Wiederherstellung war schwierig, da GitHub serverseitig kein reflog bereitstellt; mithilfe der Event API und lokaler reflogs konnte jedoch innerhalb von 7 Stunden alles wiederhergestellt werden
- npm-Pakete und Produktionsinfrastruktur wurden nicht kompromittiert
Offenlegung eines GitHub-App-Schlüssels
- Während der Untersuchung wurde im Papierkorb des Entwickler-Laptops ein privater Schlüssel einer GitHub-App gefunden
- Dieser Schlüssel hatte Lese-/Schreibrechte für Kunden-Repositories und wurde sofort rotiert
- Da die Datenbank mit den Installations-IDs nicht kompromittiert wurde, gibt es keine Belege für Zugriffe auf Kunden-Repositories; vollständig ausschließen lässt sich dies jedoch nicht
- Beim GitHub-Support wurden zusätzliche Logs angefordert und Kunden per E-Mail informiert
Technische Analyse von Shai-Hulud
- Beim Ausführen von
setup_bun.js wird die Bun-Laufzeitumgebung installiert und im Hintergrund bun_environment.js gestartet
- Mit TruffleHog werden Zugangsdaten im Verzeichnis
$HOME gesammelt
- Die gesammelten Daten (
contents.json, cloud.json, truffleSecrets.json usw.) werden in dreifach base64-kodierter Form in ein zufälliges GitHub-Repository hochgeladen
- Falls ein npm-Token vorhanden ist, verändert und veröffentlicht der Wurm Pakete des kompromittierten Kontos erneut, um sich weiterzuverbreiten
- Falls keine Zugangsdaten vorhanden sind, wird versucht, das Home-Verzeichnis zu löschen
- Dateien als Infektionsindikatoren:
setup_bun.js, bun_environment.js, .trufflehog-cache/ usw.
Maßnahmen zur Härtung der Sicherheit
- Vollständiges Deaktivieren von npm-Skripten (
ignore-scripts=true)
- Upgrade auf pnpm 10: Skripte standardmäßig deaktiviert,
minimumReleaseAge (3 Tage) gesetzt, um die Installation neuer Pakete zu verzögern
- Einführung von OIDC-basierten npm Trusted Publishers, um langfristige Tokens zu entfernen
- Branch-Schutz für alle Repositories aktiviert
- Granted für AWS SSO eingeführt, Sitzungs-Tokens verschlüsselt
- In GitHub Actions wurde für Workflow-Ausführungen von externen Mitwirkenden eine Freigabe verpflichtend gemacht
Lehren für andere Teams
- Die Ausführung beliebigen Codes während der npm-Installation ist selbst Teil der Angriffsfläche
ignore-scripts=true sollte gesetzt und nur notwendige Pakete per Whitelist zugelassen werden
- Mit pnpm minimumReleaseAge lässt sich die Installation neuer Pakete verzögern
- Branch-Schutz und OIDC-basierte Deployments sind unverzichtbare Sicherheitsmaßnahmen
- Langfristige Zugangsdaten sollten nicht auf lokalen Rechnern gespeichert werden; Deployments sollten nur über CI erlaubt sein
- Das Rauschen der Slack-Benachrichtigungen war der Schlüssel zur Erkennung
Die menschliche Seite
- Den infizierten Entwickler trifft keine Schuld; der Schaden entstand allein dadurch, dass
npm install ausgeführt wurde
- Während des Angriffs wurden Spuren gefunden, dass das Konto automatisch Hunderte zufällige Repositories mit einem Stern markiert hatte
- Der Vorfall offenbart keine individuelle Nachlässigkeit, sondern eine strukturelle Schwachstelle des Ökosystems
Kennzahlen in der Zusammenfassung
- Von der ersten Infektion bis zum ersten Angriff: etwa 2 Stunden
- Dauer des aufrechterhaltenen Zugriffs durch die Angreifer: 17 Stunden
- Dauer der destruktiven Aktionen: 10 Minuten
- Bis zur Erkennung: 5 Minuten, bis zur Blockierung: 4 Minuten
- Bis zur vollständigen Wiederherstellung: 7 Stunden
- Geklonte Repositories: 669 / Betroffene Branches: 199 / Geschlossene PRs: 42
Weiterführende Ressourcen
- Socket.dev: Shai-Hulud Strikes Again V2
- Analyseberichte von PostHog, Wiz, Endor Labs und HelixGuard
- Dokumentation zu npm Trusted Publishers, pnpm
onlyBuiltDependencies, minimumReleaseAge, Granted
Noch keine Kommentare.