4 Punkte von GN⁺ 2025-12-15 | 3 Kommentare | Auf WhatsApp teilen
  • 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

    1. 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
    Anzeige
  • 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
Anzeige

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

3 Kommentare

 
click 2025-12-15

Bei pnpm war die Struktur wohl so, dass post-install standardmäßig einzeln erlaubt werden musste, aber am Ende scheint es so zu sein, dass Entwickler es auch unbewusst erlauben.

 
lamanus 2025-12-16

Ich verstehe es so, dass npm standardmäßig ausgeführt wird und man zur Stärkung der Sicherheit auf pnpm umgestellt hat, um den Standard standardmäßig zu deaktivieren.

 
GN⁺ 2025-12-15
Hacker-News-Kommentare
  • npm install auszuführen ist nicht fahrlässig
    Das Problem ist ein Ökosystem, das bei der Paketinstallation die Ausführung beliebigen Codes erlaubt
    Das grundlegende Sicherheitsversagen ist jedoch, einen Paketmanager zu verwenden, über den Dritte ohne jede Verifikation Code in mein Produkt einschleusen können
    Am Ende sind wir grenzenlos vom guten Willen und den Fähigkeiten der Paketmanager und ihrer Betreiber abhängig
    Außerdem scheint OP anzudeuten, dass Zugangsdaten im Klartext im Dateisystem gespeichert wurden

    • Ich denke, beides ist ein Problem
      Man kann auf Sprachebene Strukturen schaffen, die Code darauf beschränken, Eingaben zu lesen, Ressourcen zu verbrauchen und nur typkorrekte Ausgaben zu erzeugen
      Das löst nicht das gesamte Supply-Chain-Problem, reduziert aber die Angriffsfläche erheblich
    • Diese Logik ist zu zirkulär
      So nach dem Motto: „Es ist nicht falsch, wenn eine Person solche Tools benutzt, aber wenn es alle tun, ist das Ökosystem das Problem“
      Dass viele Entwickler-Tools bereits sicherheitsanfällig sind, wurde oft genug bewiesen
      Wenn es einem wirklich wichtig ist, sollte man das auch durch Handeln zeigen
    • Das gilt auch für IDE-Plugins
      Bei VS Code war es lästig, dass man für jede kleine Zusatzfunktion ein Plugin installieren musste, von dem man nicht einmal weiß, wer es gebaut hat
    • Ich frage mich, wie man einen Paketmanager entwerfen könnte, der die Ausführung von Drittcode verhindert
      Am Ende läuft man doch immer auf eine Struktur hinaus, in der man zwangsläufig vertrauenswürdigen Code ausführt
    • Einige Tools unterstützen für HTTP-Authentifizierung nur eine netrc-Datei
      Wenn man Git über HTTP nutzt, gibt es fast immer einen solchen Klartext-Pfad für Zugangsdaten
  • Der pnpm-Maintainer hat schon vor einem Jahr vorgeschlagen, Post-Install-Skripte standardmäßig zu blockieren
    Für Nutzer wäre das unbequem, aber langfristig eine Änderung, für die letztlich alle dankbar wären
    Zugehöriger PR: pnpm/pnpm#8897

    • Trotzdem wiederholt sich dasselbe Problem weiterhin
      Wieder einmal ein Fall, in dem Bequemlichkeit die Sicherheit schlägt
  • Es hieß, „die Datenbank wurde nicht kompromittiert“, aber wenn Angreifer Zugriff auf AWS und Secrets hatten, würde ich das bereits als Kompromittierung werten
    Wenn die Möglichkeit des Zugriffs bestand, sollte es als kompromittiert gelten

    • Wenn es Zugriffslogs für AWS-Ressourcen gibt und vor dem Entzug der Berechtigungen keine Zugriffsspuren vorhanden sind, kann man die Daten als sicher ansehen
  • Nachdem Malware einmal ausgeführt wurde, ist die Rückverfolgung der Herkunft fast unmöglich
    Auch pnpm install läuft normal durch, daher ist das schwer zu erkennen
    Mit einem EDR wie Sentinel One oder CrowdStrike hätte man vermutlich deutlich mehr Ermittlungsansätze gehabt

    • Mit einem EDR wäre die Trufflehog-Angriffskette wahrscheinlich erkannt oder blockiert worden
  • Der Teil „insgesamt 669 Repos wurden geklont“ fiel mir auf
    Ich frage mich, ob es normal ist, dass ein Unternehmen mit weniger als 100 Mitarbeitenden über 600 Repos besitzt

    • Völlig normal. Repos sind Vieh, keine Haustiere
    • Unsere Organisation besteht aus 7 Leuten und hat 365 Repos auf GitHub
      Die Anzahl der Repos hängt stärker von Unternehmensalter und Projektlebensdauer ab als von der Teamgröße
    • Wenn man einen Architekten hat, der Microservices liebt, kommt genau so etwas dabei heraus
  • pnpm hat die automatische Ausführung von Lifecycle-Skripten wie preinstall bereits gestoppt, also wurde wohl eine alte Version verwendet
    Siehe zugehöriger PR

    • Am Ende des Artikels wird erwähnt, dass auf die aktuelle Major-Version aktualisiert wurde
    • Ich dachte, genau das sei der Hauptgrund, pnpm zu verwenden, deshalb bin ich verwirrt
    • Wenn sie letztlich Abhängigkeiten mit einem veralteten Paketmanager aktualisiert haben, dann liegt die Verantwortung bei ihnen
    • Möglich ist auch, dass das Projekt selbst ein postinstall-Skript hatte
      pnpm blockiert Skripte von Abhängigkeiten, führt aber Skripte auf Projektebene weiterhin aus
  • Danke für die transparente Veröffentlichung der Post-Mortem-Analyse
    Solche Fälle sind für die gesamte Branche wichtig
    Ich frage mich, ob sich der Angriffsverkehr vom normalen Entwicklerverkehr unterscheiden ließ
    Wir versuchen ebenfalls, die Egress-Filterung in der Dev-Umgebung zu verschärfen, aber npm install bricht dabei ständig kaputt

    • Die Funktion für IP-Allowlists von GitHub-Organisationen dürfte bei der Abwehr solcher Angriffe helfen
  • Ich denke über die Git-Sicherheit auf meinem persönlichen Laptop nach
    Derzeit pushe ich mit lokal gespeicherten SSH-Schlüsseln
    Ich habe dort auch Administratorrechte, was riskant ist. Ich frage mich, wie man das sicherer machen kann

    • Ich empfehle, mit 1Password SSH-Schlüssel und Git-Signaturen zu verwalten und für Push/Pull GitHub OAuth oder einen CLI-Login zu verwenden
      So lassen sich Signaturschlüssel und Zugriffsschlüssel trennen, und das Admin-Konto kann separat verwaltet werden
      Dokumentation dazu: 1Password SSH Agent, Git Commit Signing, GitHub OAuth, GitHub CLI Login
    • Ich speichere meinen privaten SSH-Schlüssel im TPM und nutze ihn per PKCS11 im SSH-Agent
      Das hat den Vorteil, dass der Schlüssel nicht nach außen exfiltriert werden kann, aber wenn Malware auf meinem Rechner läuft, bleibt es trotzdem riskant
      Linux-Beispiel, macOS-Beispiel
    • Wenn der Laptop infiziert ist, gibt es keine Verteidigungsmöglichkeit
      Mit TPM oder Yubikey kann man es etwas schwerer machen, aber vollständige Abwehr ist unmöglich
      Für Admin-Aufgaben ist ein separates dediziertes Gerät sicherer
    • Man kann auch einen GPG-Schlüssel auf einen Yubikey legen und mit gpg-agent SSH-Authentifizierung machen
      Beim Push oder Commit wird dann per PIN entsperrt
    • Wenn direkte Pushes auf den main-Branch blockiert werden und MFA verpflichtend ist, wird es für Angreifer schwieriger, sofort auf den Deployment-Branch zuzugreifen
  • Der Commit unter dem Namen Torvalds war ein nach einer Infektion häufig zu sehendes Erkennungszeichen (Signature)
    Das wird auch in der offiziellen Analyse von Microsoft erwähnt
    Dieser Wurm war sehr auffällig, und einige Angreifer missbrauchten offengelegte Zugangsdaten zu Werbezwecken, indem sie private Repos öffentlich machten oder Readmes veränderten

  • Ich frage mich, ob eine solche Erkennung überhaupt möglich gewesen wäre, wenn die Angreifer ohne Sabotage still nur Informationen exfiltriert hätten