Ein einfacher Schutz vor npm-Supply-Chain-Angriffen
Jedes Mal, wenn Sie npm install ausführen, vertrauen Sie Code aus Hunderten von Paketen, die Sie nie gelesen haben. Genau dieses Vertrauen nutzen Angreifer aus. Beim Shai-Hulud-Wurm im September 2025 sammelten bösartige Install-Skripte unbemerkt Anmeldedaten und veröffentlichten kompromittierte Pakete in großem Umfang erneut – alles, bevor die Eingabeaufforderung zurückkehrte. Die Axios-Kompromittierung im März 2026 folgte demselben Muster: Bösartige Versionen (1.14.1 und 0.30.4) zogen eine Abhängigkeit mit einem postinstall-Hook nach, der eine Remote-Access-Payload ausführte.
Sie benötigen kein aufwendiges Tooling, um diese Angriffsfläche zu verkleinern. Eine einzige Konfigurationsänderung adressiert den häufigsten Angriffsvektor direkt.
Wichtige Erkenntnisse
- npm-Lifecycle-Skripte (
preinstall,install,postinstall,prepare) werden automatisch mit vollen Benutzerrechten ausgeführt und stellen damit den Weg des geringsten Widerstands für Supply-Chain-Angriffe dar. - Das Setzen von
ignore-scripts=truein.npmrcblockiert den häufigsten Angriffsvektor mit nur einer einzigen Konfigurationszeile. - Pakete mit nativen Binaries wie
sharp,bcryptundsqlite3lassen sich nach einer skriptfreien Installation weiterhin selektiv mitnpm rebuildbauen. - Eine CI-Prüfung der
package-lock.jsonauf neue"hasInstallScript": true-Einträge markiert Abhängigkeiten, die vor dem Merge geprüft werden müssen. - Die Kombination aus
ignore-scripts=trueundmin-release-age=7erzeugt eine Verzögerung, die hilft, frisch kompromittierte Paketversionen zu vermeiden.
Warum Lifecycle-Skripte das Kernrisiko sind
Wenn Sie ein npm-Paket installieren, führt Node automatisch alle in seiner package.json definierten Skripte aus – preinstall, install, postinstall und prepare. Diese Hooks werden mit Ihren vollen Benutzerrechten ausgeführt und erhalten so Zugriff auf ~/.ssh, ~/.aws/credentials, ~/.npmrc-Tokens und jede Umgebungsvariable in Ihrer Shell.
Keine Bestätigungsabfrage. Keine Sandbox. Nur stille Ausführung.
Beim Axios-Angriff nutzte eine bösartige transitive Abhängigkeit namens plain-crypto-js einen postinstall-Hook, um einen Remote-Access-Trojaner abzulegen. Beim Bitwarden-CLI-Imitationsangriff initialisierte ein preinstall-Hook eine umfangreiche, obfuskierte Payload, die Cloud-Zugangsdaten sammelte und versuchte, sich über die npm-Veröffentlichungsrechte des Opfers weiterzuverbreiten.
Die Sicherheit von Lifecycle-Skripten ist deshalb so wichtig, weil sie den Angriffspfad mit dem geringsten Widerstand in der gesamten JavaScript-Abhängigkeitslandschaft darstellt.
Die zentrale Verteidigung: npm ignore-scripts
Fügen Sie eine Zeile zur .npmrc Ihres Projekts hinzu:
ignore-scripts=true
Dies weist npm an, alle Lifecycle-Skripte während der Installation zu überspringen. Ein bösartiger postinstall-Hook wird schlicht nicht ausgeführt.
Für eine einmalige Installation ohne Änderung der .npmrc:
npm install --ignore-scripts
Wichtiger Hinweis: Dies ist keine vollständige Lösung. Beim Bitwarden-Angriff wurde ein bösartiges Binary über das bin-Feld in der package.json registriert, sodass die Payload trotzdem ausgeführt wurde, sobald ein Benutzer den bw-Befehl aufrief – auch bei aktivem --ignore-scripts. Kein einzelnes Flag eliminiert sämtliche Risiken.
Was bricht und wie Sie damit umgehen
Einige legitime Pakete benötigen Lifecycle-Skripte, um native Binaries zu kompilieren. Häufige Beispiele sind sharp, bcrypt, sqlite3, canvas und puppeteer (das Chromium herunterlädt).
Prüfen Sie, ob Ihr Projekt eines davon verwendet:
npm ls --all | grep -E "(sharp|bcrypt|sqlite3|canvas|puppeteer|node-gyp)"
Wenn Sie Treffer erhalten, bauen Sie nur diese spezifischen Pakete nach der Installation neu:
npm install --ignore-scripts
npm rebuild sharp --ignore-scripts=false
npm rebuild bcrypt --ignore-scripts=false
Dieser Ansatz hält Skripte global deaktiviert und erlaubt die Kompilierung selektiv nur für Pakete, die Sie ausdrücklich geprüft haben.
Discover how at OpenReplay.com.
Neue Install-Skripte erkennen, bevor sie ausgeführt werden
Anstatt erst im Nachhinein zu reagieren, sollten Sie neue Abhängigkeiten mit Install-Skripten vor dem Merge markieren. Fügen Sie diese Prüfung Ihrer CI-Pipeline hinzu:
# Detect newly added packages with install scripts in PRs
if git diff origin/main -- package-lock.json | \
grep -E '^\+\s*"hasInstallScript": true' > /dev/null; then
echo "⚠️ New install script detected—manual review required"
exit 1
else
echo "✅ No new install scripts"
fi
Beim Axios-Angriff war plain-crypto-js eine brandneue Abhängigkeit mit einem postinstall-Hook. Diese Prüfung hätte sie vor dem PR-Merge markiert.
Details dazu, wie npm Install-Skripte in Lockfiles dokumentiert, finden Sie in der offiziellen package-lock.json-Dokumentation.
Was diese Schutzmaßnahmen nicht abdecken
Seien Sie ehrlich, was die Grenzen angeht:
- Lockfiles verhindern keine Angriffe, wenn ein Entwickler während des Kompromittierungsfensters
npm installausgeführt und das Lockfile vergiftet hat, bevor Sie es bemerkt haben. npm auditerfasst nur bekannte bösartige Pakete – neuartige Angriffe erscheinen nicht in seiner Datenbank.- 2FA für npm-Konten schützt Konsumenten nicht vor einem Paket, das von einem kompromittierten Maintainer legitim veröffentlicht wurde.
--ignore-scriptsblockiert keinen bösartigen Code, der im eigentlichen Laufzeit-JavaScript des Pakets eingebettet ist.
Ein mehrschichtiger Ansatz hilft. Kombinieren Sie ignore-scripts=true mit min-release-age=7 in der .npmrc (erfordert npm v11.10.0 oder neuer), um die Installation von Paketen zu vermeiden, die in der letzten Woche veröffentlicht wurden – jenes Fenster, in dem die meisten Angriffe aktiv und unentdeckt sind. Diese Einstellung ist in der npm-Config-Dokumentation unter min-release-age beschrieben.
So fangen Sie an
Fügen Sie heute Folgendes zu Ihrer .npmrc hinzu:
ignore-scripts=true
min-release-age=7
Ergänzen Sie dann die CI-Prüfung auf neue hasInstallScript-Einträge bei jedem PR, der package-lock.json ändert. Diese beiden Änderungen adressieren das Angriffsmuster der jüngsten npm-Supply-Chain-Angriffe – ohne neue Tools, kostenpflichtige Dienste oder umfangreiche Workflow-Änderungen.
Fazit
Sie können nicht jede Zeile jedes Pakets lesen, von dem Sie abhängen, aber Sie können stark einschränken, was diese Pakete während der Installation tun dürfen. Lifecycle-Skripte standardmäßig zu deaktivieren, nur die nativen Pakete neu zu bauen, denen Sie vertrauen, und neue hasInstallScript-Einträge in der CI zu markieren – diese Maßnahmen zusammen neutralisieren den am stärksten ausgenutzten Angriffsvektor im npm-Ökosystem. Keine dieser Maßnahmen erfordert neue Anbieter oder Budget – nur ein paar Zeilen in der .npmrc und eine einzige CI-Prüfung. Setzen Sie sie heute um, und der nächste Angriff im Stil von Shai-Hulud wird für Ihr Projekt deutlich weniger folgenreich sein.
FAQs
Es kann Pakete betreffen, die während der Installation native Binaries kompilieren, etwa sharp, bcrypt, sqlite3, canvas und puppeteer. Führen Sie nach npm install mit deaktivierten Skripten npm rebuild gefolgt vom Paketnamen mit --ignore-scripts=false aus, um nur die geprüften und vertrauenswürdigen Pakete zu kompilieren. Die meisten reinen JavaScript-Abhängigkeiten funktionieren ohne Änderungen.
Nein. Es blockiert den häufigsten Vektor – Lifecycle-Hooks wie postinstall –, stoppt aber weder bösartigen Code im Laufzeit-JavaScript eines Pakets noch ein bösartiges Binary, das über das bin-Feld registriert wird. Der Bitwarden-CLI-Imitationsangriff hat ignore-scripts auf diese Weise umgangen. Kombinieren Sie es mit min-release-age, Lockfile-Reviews und Dependency-Auditing für eine mehrschichtige Verteidigung.
Die Einstellung min-release-age erfordert npm-Version 11.10.0 oder neuer. Prüfen Sie Ihre Version mit npm --version und aktualisieren Sie bei Bedarf mit npm install -g npm@latest. Überprüfen Sie nach der Konfiguration mit npm config get min-release-age, ob die Einstellung aktiv ist.
Committen Sie Ihre .npmrc-Datei mit ignore-scripts=true ins Repository, sodass die CI die Einstellung automatisch übernimmt. Für Builds, die tatsächlich native Kompilierung benötigen, fügen Sie explizite npm rebuild-Befehle (mit --ignore-scripts=false) für die jeweils benötigten Pakete hinzu. So bleibt der sichere Standard erhalten und es ist gleichzeitig dokumentiert, welche Pakete Installationscode ausführen dürfen.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.