Supply-Chain-Angriffe mit pnpm verhindern

Supply-Chain-Attacks werden immer häufiger. pnpm hilft dabei diesem Problem zu begegnen und bietet noch weitere Vorteile gegenüber npm.

Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH
Logo von , Kunde der blecon GmbH

Was ist ein Supply-Chain-Angriff?

Bei einem Supply-Chain-Angriff („Zuliefer-Ketten-Angriff“) werden ein oder mehrere Software-Projekte kompromittiert, indem ein von ihnen genutztes Software-Paket, eine „Abhängigkeit“, kompromittiert wird. Der kompromittierte Code ist nicht unter der Kontrolle der Projektmitarbeiter. Heutige Softwareprojekte haben oft viele Abhängigkeiten und diese werden mit verschiedenen Package-Manager-Tools („Paketverwaltungs-Werkzeugen“) verwaltet und installiert.

Was ist das spezifische Problem?

Supply-Chain-Angriffe werden immer häufiger. Das letzte große Beispiel ist die Kompromittierung des axios npm-Pakets. npm (Node Package Manager) ist eine Paketverwaltung für JavaScript Code. Egal wie die jeweiligen Software-Pakete kompromittiert wurden, taucht ein Angriffsvektor immer wieder auf: "postintall"-Scripte. Diese Scripte, auch Hooks genannt, sind zum Ausführen von weiteren Installationsschritten nach dem Herunterladen von Paketen gedacht und sind npm-spezifisch. Andere Package-Manager besitzen allerdings ähnliche Mechanismen, die auch schon als Angriffsvektor missbraucht wurden. Theoretisch können auch andere Hooks als Angriffsvektor missbraucht werden, nicht nur der "postinstall" Hook. Der kritische Punkt, warum diese Angriffe so erfolgreich sind, liegt allerdings darin, dass diese Scripte ohne Nutzerinteraktion ausgeführt werden. Noch kritischer wird es dadurch, dass nicht nur direkte Abhängigkeiten, sondern auch indirekte, transitive Abhängigkeiten Scripte ausführen können. npm hat zwar eine --ignore-scripts Option, allerdings deaktiviert diese sämtliche Scripte, von allen Paketen. Man hat damit keine Möglichkeit nur einzelne Scripte laufen zu lassen. Es gibt eine seit 2019 laufende RFC-Diskussion und einen offenen Pull-Request, selektives Ausführen von Skripten in npm zu ermöglichen, allerdings sind diese scheinbar gegen Ende 2021 eingeschlafen.

Eine Lösung: pnpm

Das ist einer der Gründe warum ich mittlerweile empfehle pnpm anstatt npm zu benutzen. pnpm fragt den Nutzer vor dem Ausführen von Scripten um Erlaubnis und man kann sich einzeln per Script entscheiden, ob man es ausführen will oder nicht. Dieser einfache Mechanismus macht den Angriffsvektor Scripte nicht komplett unmöglich, aber man hat mit diesem Mechanismus als Benutzer zumindest eine Verteidigungslinie.

Weitere Vorteile von pnpm

Darüber hinaus bietet pnpm noch weitere Vorteile, wie zum Beispiel die bessere Nutzung von Speicherplatz durch Abhängigkeiten. npm installiert sämtliche Abhängigkeiten für jedes Projekt erneut im node_modules Ordner des Projektes. Dadurch liegen Duplikate der selben Abhängigkeit in jedem Projekt auf dem System. Außerdem wird jede Version einer Abhängigkeit komplett auf dem System gespeichert, selbst wenn sich nur eine Datei unterscheidet. Dadurch kann es sehr schnell passieren, dass in einem npm Projekt der node_modules Ordner von mehreren hundert Megabyte bis zu mehreren Gigabyte wachsen kann. pnpm vermeidet diese Duplikate und speichert sämtliche Pakete an einem zentralen Platz im System, auch über Projekte hinweg. Zusätzlich werden für unterschiedliche Versionen des selben Pakets nur die unterschiedlichen Dateien gespeichert. Gleiche Dateien werden wiederverwendet. Dadurch reduziert pnpm die Größe des node_modules Ordners problemlos auf unter einhundert Megabyte. Außerdem wird dadurch verhindert, die gleichen Abhängigkeiten für neue Projekte immer wieder herunter laden zu müssen.

Umstellung von npm auf pnpm

Für die meisten Projekte sollte es ohne große Umstellung möglich sein, von npm auf pnpm umzustellen:

  1. Zuerst muss pnpm installiert werden. Am einfachst geht dies mit npm selbst: npm install --global pnpm
    Alternativen kann man in pnpm’s Dokumentation finden.
  2. Als nächstes muss man den node_modules Ordner des Projektes löschen, dass man umstellen will.
  3. (Optional) Man kann mit Hilfe des Paketes only-allow erzwingen, dass nur pnpm als Package-Manager zulässig ist. Dazu muss man folgendes zur package.json Datei des Projektes hinzufügen: "scripts": { "preinstall": "npx only-allow pnpm" }
  4. Anschließend muss man pnpm die aktuelle Konfiguration der Abhängigkeiten importieren lassen: pnpm import
  5. Danach muss man die package-lock.json Datei löschen.
  6. Zuletzt lässt man pnpm die Abhängigkeiten wieder installieren und den node_modules neu generieren: pnpm install

Danach sollten die meisten npm Befehle in pnpm ähnlich funktionieren, man muss nur pnpm anstatt npm als Werkzeug benutzen. Für mehr Information dient die pnpm Dokumentation.

Es gibt einzelne Dinge, die unter pnpm anders funktionieren, diese sind aber eher selten und führen hier zu weit. Für weitere Informationen um Supply-Chain-Angriffe mit pnpm zu verhindern verweise ich auf diesen Eintrag in pnpm’s Dokumentation.

Beitrag veröffentlicht am 7. Apr. 2026

verfasst von Kai Moschcau