- Die Seattle Times ist dem Angriff Shai-Hulud 2.0 zufällig entgangen, hat aber unter der Prämisse, dass Glück keine Sicherheitsstrategie sein kann, clientseitige Abwehrmaßnahmen eingeführt
- Verbesserungen bei npm wie Trusted Publishing / Provenance / granulare Tokens stärken die Seite des „Veröffentlichens“, lassen aber eine Lücke offen: die Ausführung von Schadcode beim „Installieren/Aktualisieren“ wird dadurch nicht verhindert
- pnpm verwendet weiterhin das npm-Registry, ergänzt aber Kontrollen, die die Ausführung bösartiger Pakete in der Konsumphase (install/update) erschweren
- Im Pilotprojekt wurden drei Kontrollen von pnpm angewendet, die jeweils Vektoren wie die Ausführung von Lifecycle-Skripten, die sofortige Installation neuester Releases und Vertrauens-Downgrades blockieren sollen
- Ausnahmen werden nicht als Scheitern, sondern als Teil des Designs betrachtet; Ziel ist ein Betrieb nach dem Prinzip Defense-in-Depth, bei dem Ausnahmen dokumentiert werden und die übrigen Ebenen weiter schützen
Hintergrund des Vorfalls und Grundannahmen
- Im November 2025 trat ein Fall auf, bei dem ein selbstreplizierender npm-Wurm 796 Pakete infizierte und sich über monatlich 132 Millionen Downloads verbreitete
- Der Angriff nutzte preinstall-Skripte, um Zugangsdaten zu stehlen, persistente Backdoors zu installieren und in manchen Umgebungen sogar Entwicklungsumgebungen zu löschen
- Dass unsere Organisation nicht betroffen war, lag nicht an starker Abwehr, sondern am Zufall, dass während des Angriffs kein
npm install bzw. npm update ausgeführt wurde
- Für Nachrichtenorganisationen ist Vertrauen zentral; durch eine Kompromittierung der Lieferkette könnten Kundendaten, Mitarbeiter-Zugangsdaten, Produktionsinfrastruktur und Quellcode offengelegt werden, zudem sind Wiederherstellung und Benachrichtigung teuer
Team und Einführungskontext
- Die Seattle Times nutzt seit Langem npm als Standard-Paketmanager; es gab auch Experimente mit Yarn, die sich aber nicht durchgesetzt haben
- Der Grund für die Einführung von pnpm sind clientseitige Sicherheitskontrollen als Ergänzung zu Verbesserungen auf Registry-Ebene
- pnpm wurde als Drop-in Replacement mit demselben Registry, denselben Befehlen und demselben Workflow eingeschätzt, wodurch ein Wechsel realistisch erschien
- Es handelt sich nicht um eine abgeschlossene Case Study, sondern um die geteilten Probleme und Denkprozesse eines realen Teams, das gerade erst mit Supply-Chain-Sicherheit beginnt
Warum clientseitige Kontrollen nötig sind
- Durch Sicherheitsverbesserungen bei npm ist die Veröffentlichung bösartiger Pakete nach einer Kontoübernahme schwieriger geworden
- Diese Verbesserungen schützen die Seite des „Publishings“, verhindern aber nicht die Installation bösartiger Pakete in der Phase des „Consumings“
- Bei
npm install/npm update können Lifecycle-Skripte (preinstall/postinstall usw.) beliebigen Code mit Entwicklerrechten ausführen, noch bevor die Sicherheit eines Pakets bewertet wurde
- Die Skripte können auf npm-/GitHub-/AWS-/DB-Zugangsdaten, Quellcode, Cloud-Infrastruktur und das gesamte Dateisystem zugreifen
- Angriffe wie Shai-Hulud missbrauchen genau diese Struktur; wird ein Maintainer-Konto übernommen, kann ein bösartiges Skript im Moment der Installation ausgeführt werden, bevor die Community den Vorfall erkennt
- Die Verbesserungen von npm auf der Publishing-Seite und die Kontrollen von pnpm auf der Konsum-Seite werden als komplementäre Abwehr zu einer „Defense-in-Depth“-Strategie kombiniert
Die 3 eingesetzten Ebenen
- Im Pilotprojekt wurden drei Kontrollen gemeinsam eingesetzt, die auf unterschiedliche Angriffsvektoren zielen
- Jede Kontrolle enthält einen realistischen Ausweg für Ausnahmen und ist von vornherein unter der Annahme entworfen, dass Ausnahmen in echten Umgebungen nötig sind
Control 1: Lifecycle Script Management
- pnpm blockiert standardmäßig Lifecycle-Skripte, während die Installation mit Warnungen fortgesetzt werden kann
- Aus Sorge, dass Warnungen ignoriert werden könnten, wurde
strictDepBuilds: true gewählt, sodass die Installation sofort fehlschlägt, sobald Skripte vorhanden sind
- Das Konfigurationsbeispiel in
pnpm-workspace.yaml besteht aus den folgenden Feldern
strictDepBuilds: true
onlyBuiltDependencies: Allowlist für Pakete mit nötigen Build-Skripten
ignoredBuiltDependencies: Blocklist (oder Ignore-Liste) für Pakete mit unnötigen Build-Skripten
- Als „nötige Skripte“ gelten Vorgänge wie das Kompilieren nativer Erweiterungen oder das Verlinken plattformabhängiger Bibliotheken
- Als „unnötige Skripte“ gelten Optimierungen oder optionale Konfigurationen, die die Funktion im Nutzungskontext des Teams nicht beeinflussen
- Das Scheitern der Installation erzwingt die nächsten Schritte
- pnpm zeigt klar an, welche Pakete Skripte enthalten
- Das Verhalten der Skripte wird untersucht und verstanden
- Die Entscheidung über Zulassen/Blockieren wird bewusst durch Menschen getroffen und dokumentiert
- Das pnpm-Team erwägt für v11
strictDepBuilds: true als Standard und prüft auch bessere Namen für die Allow/Deny-Syntax
Control 2: Release Cooldown
- Kürzlich veröffentlichte Versionen werden für einen bestimmten Cooldown-Zeitraum von der Installation ausgeschlossen, damit die Community Zeit hat, bösartige Pakete zu erkennen und zu entfernen
- Das Konfigurationsbeispiel in
pnpm-workspace.yaml besteht aus den folgenden Feldern
minimumReleaseAge: <duration-in-minutes>
minimumReleaseAgeExclude: Allowlist für Ausnahmen wie dringende Hotfixes
- Dafür ist ein Umdenken nötig: weg von der Gewohnheit „neueste Version ist am besten“ hin zu der Sicht, dass aus Supply-Chain-Perspektive etwas ältere Versionen sicherer sein können
- Beim Angriff im September 2025 (16 Pakete einschließlich debug und chalk) dauerte die Entfernung etwa 2,5 Stunden, bei Shai-Hulud 2.0 im November 2025 etwa 12 Stunden
- Je nach Risikotoleranz der Organisation kann der Cooldown Stunden, Tage oder Wochen betragen; in jeder Form hätte er den jeweiligen Angriff verhindert
- Das passt gut zur Realität, dass Organisationen ohnehin nicht immer sofort die neueste Version einsetzen können, sodass der Cooldown die Arbeit nicht stark behindert
- Bei zwingenden Fällen wie Security-Patches oder kritischen Bugs können Ausnahmen nach Prüfung freigegeben werden
Control 3: Trust Policy
- Wenn eine Version mit schwächerer Authentisierung veröffentlicht wurde als die vorherige, wird ihre Installation blockiert
- Das wird als Signal gewertet, dass ein Maintainer-Konto kompromittiert wurde und die Veröffentlichung nicht aus der offiziellen CI/CD, sondern von einem Angreifer-System erfolgte
- Das Konfigurationsbeispiel in
pnpm-workspace.yaml besteht aus den folgenden Feldern
trustPolicy: no-downgrade
trustPolicyExclude: Allowlist für Ausnahmen wie CI/CD-Migrationen
- npm verfolgt laut Beschreibung für Paketveröffentlichungen drei Vertrauensstufen (stark → schwach)
- Trusted Publisher: auf Basis von GitHub Actions + OIDC + npm Provenance
- Provenance: signierte Attestation aus der CI/CD
- No Trust Evidence: Veröffentlichung per Benutzername/Passwort oder Token
- Sinkt die Vertrauensstufe einer neuen Version unter die der vorherigen, schlägt die Installation fehl
- Beim Angriff s1ngularity im August 2025 wurde lokal ohne CI/CD-Zugriff eine bösartige Version veröffentlicht, die keine Provenance hatte; diese Kontrolle hätte die Installation verhindert
- Als Fälle legitimer Downgrades werden neue Maintainer, CI/CD-Migrationen oder manuelle Hotfixes bei Ausfällen der CI/CD genannt; nach Untersuchung werden sie in die Ausnahmeliste aufgenommen
- Diese Funktion ist ein neues Feature, das im November 2025 zu pnpm hinzugefügt wurde; wie häufig legitime Downgrades in der Praxis auftreten, wird noch gelernt
Beispiel für das Zusammenspiel der Ebenen: React-Patch für eine Schwachstelle
- Im Szenario, dass ein im Dezember 2025 veröffentlichter Patch für eine kritische Schwachstelle in React Server Components sofort eingespielt werden muss
- Normalerweise würde der Cooldown die „Installation einer gerade veröffentlichten Version“ blockieren, aber bei einem kritischen Security-Patch kann man nicht warten
- In diesem Fall wird die konkrete React-Version zu
minimumReleaseAgeExclude hinzugefügt, nachdem der Sicherheitshinweis und die Legitimität des Patches geprüft wurden
- Auch mit dieser Ausnahme schützen die anderen Ebenen weiter
- React hat normalerweise keine Lifecycle-Skripte; tauchen solche in einem Patch-Release auf, ist das sofort ein Warnsignal und kann blockiert werden
- Wenn ein Angreifer Zugangsdaten stiehlt und lokal einen „Patch“ veröffentlicht, kann dies durch den Vertrauens-Downgrade blockiert werden
- Ausnahmen gelten nicht als „Sicherheitsversagen“, sondern als Design, bei dem beim Umgehen einer Ebene andere Ebenen erhalten bleiben und kein Single Point of Failure entsteht
Ergebnis des Piloten
- Es wurde ein PoC durchgeführt, bei dem alle drei Kontrollen auf einen Backend-Service angewendet wurden
- Die gesamte Vorbereitungszeit für Untersuchung, Verständnis und Definition des Vorgehens lag bei einigen Stunden
- pnpm identifizierte drei Pakete mit Lifecycle-Skripten
- esbuild: optimiert den Start der CLI um Millisekunden, wurde aber als unnötig bewertet, da das Team nur die JS-API nutzt
- @firebase/util: automatische Konfiguration für das Client-SDK, wurde aber als unnötig bewertet, da das Team nur das Server-SDK nutzt
- protobufjs: Prüfung der Schema-Kompatibilität, wird nur als transitive Abhängigkeit genutzt und galt im Nutzungsszenario des Teams als unnötig
- Nach Sichtung der Dokumentation und Analyse der Skripte (einschließlich KI-gestützter Hilfe bei der Interpretation) kam das Team zum Schluss, dass alle drei Skripte für den eigenen Anwendungsfall nicht nötig sind, und blockierte sie
- Es gab keine funktionalen Auswirkungen
- Reibung (friction) ist hier eine beabsichtigte Funktion: ein Zwangsmechanismus, um Code, der in der Umgebung läuft, nicht mehr implizit zu vertrauen
- Wenn eine neue Abhängigkeit Skripte enthält, wird für Review und Dokumentation mit etwa 15 Minuten Aufwand gerechnet
Erkenntnisse im Betrieb
- Die Kombination aus clientseitigen Ebenen und den Verbesserungen von npm auf der Publishing-Seite vermittelt, dass Defense-in-Depth tatsächlich funktioniert
- Auch wenn Ausnahmen angewendet werden, bleiben andere Ebenen bestehen, was die Sorge über Ausnahmen reduziert
- Der Wechsel des mentalen Modells von „Bequemlichkeit zuerst“ zu „Sicherheit zuerst“ braucht Zeit, fühlt sich aber nach einer Eingewöhnung natürlich an
- Die Maßnahmen sind auch für mittelgroße Organisationen ohne dediziertes Security-Team praktisch umsetzbar
- Die Trust Policy ist erst seit wenigen Wochen verfügbar, daher müssen Häufigkeit legitimer Downgrades und die operative Handhabung noch weiter gelernt werden
- In naher Zukunft ist eine Ausweitung auf weitere Codebasen geplant, wodurch mehr Daten aus Anwendungen mit anderen Abhängigkeitsgraphen zusammenkommen werden
Tipps für andere Teams
- Empfohlen wird, zuerst mit einem Projekt zu starten und dabei Workflow sowie Reibungspunkte kennenzulernen
- Da bei Lifecycle-Skripten, Release-Cooldown und Trust-Downgrade überall Ausnahmen nötig sein können, sollte von Anfang an mit Ausnahmen geplant werden
- Empfohlen wird die Strategie,
strictDepBuilds: true von Tag eins an zu verwenden statt eines warnungsbasierten Ansatzes
- Alle Ausnahmen sollten dokumentiert werden, um einen Audit-Trail zu hinterlassen und spätere Bereinigung zu erleichtern
- Wichtig ist, im Kopf zu behalten, dass eine Ausnahme in einer Ebene den Schutz der anderen Ebenen bestehen lässt
Noch keine Kommentare.