3 Punkte von GN⁺ 2025-12-19 | Noch keine Kommentare. | Auf WhatsApp teilen
  • 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.

Noch keine Kommentare.