npm-Sicherheits-Best-Practices
Das npm-Ökosystem ist die größte Paket-Registry der Welt, und diese Größenordnung macht es zu einem hochattraktiven Angriffsziel. Angriffe wie Shai-Hulud, event-stream und eslint-scope haben alle dieselbe unbequeme Wahrheit demonstriert: Die Installation eines Pakets kann beliebigen Code auf Ihrem Rechner ausführen, bevor Sie auch nur eine einzige Zeile des Quellcodes gelesen haben. Diese npm-Sicherheits-Best-Practices helfen Ihnen, dieses Risiko in jeder Phase zu reduzieren – beim Installieren, Entwickeln und Veröffentlichen.
Wichtigste Erkenntnisse
- Deaktivieren Sie Post-Install-Skripte global und setzen Sie nur die Pakete auf eine Allowlist, die sie wirklich benötigen.
- Legen Sie eine Release-Age-Cooldown fest, sodass brandneue (und potenziell bösartige) Versionen niemals automatisch in Ihre Builds gelangen.
- Committen Sie immer Ihre Lockfile und verwenden Sie
npm ciin CI-Pipelines für reproduzierbare, manipulationssichere Installationen. - Schützen Sie Maintainer-Accounts mit WebAuthn-basierter 2FA und veröffentlichen Sie über OIDC Trusted Publishing, um langlebige Token zu eliminieren.
Warum npm-Supply-Chain-Sicherheit jetzt wichtig ist
Supply-Chain-Angriffe nutzen nicht Ihren Code aus. Sie nutzen Ihr Vertrauen in den Code anderer aus. Wenn ein kompromittiertes Paket in Ihren node_modules landet, kann es Zugangsdaten stehlen, Umgebungsvariablen exfiltrieren oder sich selbst weiter verbreiten. Allein der Shai-Hulud-Wurm führte in einem einzigen Vorfall zur Entfernung von über 500 Paketen aus der Registry. Vulnerability-Scanning allein wird diese Klasse von Angriffen nicht erkennen – Sie benötigen Defense in Depth.
Sichere Dependency-Verwaltung: Härten Sie Ihre Installationen
Post-Install-Skripte deaktivieren
Post-Install-Skripte sind der häufigste Angriffsvektor bei npm-Supply-Chain-Angriffen. Deaktivieren Sie sie global:
npm config set ignore-scripts true
npm config set allow-git none # npm CLI 11.10.0+
Die Einstellung allow-git=none ist wichtig, weil eine git-basierte Dependency ihre eigene .npmrc mitbringen kann, die Lifecycle-Skripte stillschweigend wieder aktiviert und ignore-scripts vollständig umgeht.
Wenn Sie pnpm verwenden, deaktiviert Version 10+ Post-Install-Skripte standardmäßig. Verwenden Sie pnpm-workspace.yaml, um Pakete explizit auf eine Allowlist zu setzen, die sie legitim benötigen:
allowBuilds:
esbuild: true
core-js: false
Aktivieren Sie strictDepBuilds: true, um jedes nicht überprüfte Build-Skript in einen CI-blockierenden Fehler statt in eine stille Warnung zu verwandeln. Bun blockiert Post-Install-Skripte ebenfalls standardmäßig, mit Opt-in über trustedDependencies in package.json.
Wenn Sie Lifecycle-Skripte benötigen, verwenden Sie @lavamoat/allow-scripts, um eine prüfbare Allowlist zu erstellen, anstatt Skripte global zu aktivieren.
Release-Age-Cooldown hinzufügen
Bösartige Pakete werden oft innerhalb von Stunden oder Tagen entdeckt und depubliziert. Das Überspringen brandneuer Versionen gibt der Community Zeit, Probleme zu erkennen, bevor sie Sie erreichen:
npm config set min-release-age 3
Dies weist npm an, jede Paketversion zu ignorieren, die vor weniger als drei Tagen veröffentlicht wurde. Für automatisierte Dependency-Updates unterstützen Tools wie Renovate und Dependabot äquivalente minimumReleaseAge-Einstellungen.
Committen Sie Ihre Lockfile und verwenden Sie npm ci
Committen Sie immer package-lock.json. Ersetzen Sie in CI-Umgebungen npm install durch:
npm ci
npm ci installiert ausschließlich aus der Lockfile, schlägt bei jeder Abweichung fehl und löst niemals stillschweigend eine andere Version auf. Dies ist die Grundlage für reproduzierbare, sichere Builds in automatisierten Pipelines.
Nicht blind upgraden
npm audit und npm outdated sind nützliche Signale, aber behandeln Sie sie als einen Input, nicht als vollständige Lösung. Überprüfen Sie vor dem Upgrade einer Dependency das Changelog. Vermeiden Sie Massen-Upgrades, die diesen Schritt überspringen – jedes Versions-Bump ist eine potenzielle Änderung der Angriffsfläche.
Discover how at OpenReplay.com.
Sichere npm-Workflows für Paket-Maintainer
2FA aktivieren – und auf WebAuthn upgraden
Account-Übernahmen sind der primäre Mechanismus hinter Supply-Chain-Angriffen auf die Registry. Aktivieren Sie 2FA auf Ihrem npm-Account mit Write-Mode-Schutz:
npm profile enable-2fa auth-and-writes
GitHub fördert zunehmend Passkeys und WebAuthn-basierte Authentifizierung, die deutlich phishing-resistenter sind als traditionelle TOTP-basierte 2FA. Ein Hardware-Key oder Passkey ist wesentlich schwerer zu phishen als ein TOTP-Code, daher lohnt sich ein frühzeitiger Wechsel.
Mit Trusted Publishing (OIDC) veröffentlichen
Langlebige npm-Token sind ein Risiko. Trusted Publishing über OIDC ermöglicht es GitHub Actions oder GitLab CI, sich direkt bei npm mit kurzlebigen, workflow-spezifischen Credentials zu authentifizieren – kein gespeicherter Token erforderlich. Es generiert auch automatisch Provenance-Attestierungen, die Konsumenten einen kryptografischen Nachweis darüber geben, wo und wie ein Paket gebaut wurde.
Dies ist die Richtung, in die sich das Ökosystem bewegt. GitHub hat Pläne signalisiert, Legacy-Token schrittweise abzuschaffen und Trusted Publishing zum Standard-Pfad für Automatisierung zu machen.
Verifizieren Sie, was Sie installieren
Gehen Sie nicht davon aus, dass die offizielle Registry sicher ist. Verwenden Sie Socket oder npq, um Pakete vor der Installation auf verdächtiges Verhalten zu prüfen. Überprüfen Sie Download-Zahlen, Repository-Aktivität und Maintainer-Historie – insbesondere bei Paketen, die von KI-Coding-Assistenten vorgeschlagen werden, die Paketnamen halluzinieren können, die Angreifer dann registrieren (eine Technik namens Slopsquatting).
Fazit
Kein einzelnes Tool verhindert jeden npm-Supply-Chain-Angriff. Die wichtigsten Praktiken sind mehrschichtig: Lifecycle-Skripte deaktivieren, Lockfiles durchsetzen, einen Cooldown für neue Versionen hinzufügen, npm ci in CI verwenden und Publishing auf OIDC mit 2FA umstellen. Jede Schicht reduziert das Risiko unabhängig. Zusammen machen sie Ihren Workflow deutlich schwerer kompromittierbar.
FAQs
Ja, einige Pakete wie esbuild oder sharp benötigen Post-Install-Skripte, um plattformspezifische Binaries herunterzuladen. Anstatt Skripte global wieder zu aktivieren, verwenden Sie einen Allowlist-Ansatz mit pnpms allowBuilds-Konfiguration oder LavaMoats allow-scripts, um nur spezifischen, vertrauenswürdigen Paketen Berechtigung zu erteilen, die tatsächlich Build-Schritte benötigen.
Nein. npm audit prüft auf bekannte Schwachstellen in veröffentlichten Advisories, kann aber neuartige Supply-Chain-Angriffe wie Typosquatting, Account-Übernahmen oder bösartigen Code, der in ansonsten legitime Pakete injiziert wurde, nicht erkennen. Behandeln Sie audit als ein nützliches Signal innerhalb einer breiteren mehrschichtigen Verteidigungsstrategie, die Lockfile-Durchsetzung, Skript-Beschränkungen und Pre-Install-Screening-Tools umfasst.
npm install liest package.json, löst Dependency-Ranges auf und kann die Lockfile modifizieren. npm ci liest nur aus package-lock.json, installiert exakte Versionen und schlägt sofort fehl, wenn die Lockfile fehlt oder inkonsistent mit package.json ist. Verwenden Sie immer npm ci in Continuous-Integration-Pipelines, um reproduzierbare und manipulationssichere Builds zu garantieren.
Traditionelle npm-Token sind langlebige Secrets, die in CI-Umgebungen gespeichert werden, was sie zu attraktiven Diebstahlszielen macht. OIDC Trusted Publishing generiert kurzlebige, workflow-spezifische Credentials, die an ein bestimmtes Repository und einen Action-Run gebunden sind. Kein Secret wird irgendwo gespeichert, und jede Publish-Operation ist kryptografisch mit ihrer Quelle verknüpft, wodurch automatisch verifizierbare Provenance-Attestierungen erzeugt werden.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before 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.