7 Tipps, um Hacks zu vermeiden (npm, pnpm & bun)

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00Wenn Sie NPM-Pakete installieren, sind Sie ein Ziel. Vielleicht nicht heute, vielleicht nicht diese Woche, aber es
00:00:05passiert definitiv. Wir hatten allein in den letzten Monaten Hunderte von kompromittierten Paketen,
00:00:09und das lässt nicht nach. Also, statt mich jedes Mal zu sorgen, wenn so etwas auftaucht,
00:00:14habe ich tatsächlich mein eigenes Setup für NPM, PNPM und BUN abgesichert, und es stellt sich heraus,
00:00:18dass das meiste, was Sie hätte retten können, in etwa 30 Sekunden eingerichtet ist. Also in diesem Video
00:00:23führe ich Sie durch die sieben Änderungen, die ich vorgenommen habe – von einer einzigen Konfigurationszeile,
00:00:27die den häufigsten Angriff sofort stoppt, bis hin zu kostenlosen Tools, die von den Angreifern selbst
00:00:30eingereicht wurden, um sie zu fangen, bevor das Paket überhaupt Ihren Rechner erreicht. Fangen wir an.
00:00:39Der erste und einfachste Schritt ist, einfach keine neuen Pakete mehr herunterzuladen. Die meisten dieser
00:00:44Supply-Chain-Angriffe werden innerhalb weniger Stunden erkannt. Wenn Sie also brandneue Versionen nicht
00:00:48sofort installieren, sobald sie erscheinen, umgehen Sie tatsächlich die meisten dieser Supply-Chain-Angriffe.
00:00:52Alle wichtigen Node.js-Paketmanager bieten inzwischen eine Form von Releas-Alter-Begrenzung. Für NPM stellen Sie
00:00:57dies in der .npmrc-Datei in Tagen ein. Für PNPM können Sie dies global in der pnpm-config.yaml-Datei festlegen,
00:01:03oder Sie können dies pro Projekt in der pnpm-workspace.yaml-Datei tun, wobei dieser Wert in Minuten angegeben wird.
00:01:08Und es ist erwähnenswert, dass PNPM seit Version 11 dies standardmäßig auf einen Tag gesetzt hat,
00:01:14sodass Sie selbst ohne Konfiguration einen gewissen Schutz haben. Bei BUN stellen Sie dies in der
00:01:17bunfig.toml-Datei ein, entweder global oder pro Projekt, und hier erfolgt die Einstellung in Sekunden.
00:01:23Es erstaunt mich wirklich, dass wir bei drei Paketmanagern für dieselbe Einstellung bei
00:01:27drei verschiedenen Einheiten gelandet sind; das fasst das Ökosystem ganz gut zusammen. Sobald dies eingestellt ist,
00:01:32und Sie ein Paket wie TanStacks react-start installieren, sehen Sie, dass nicht die neueste,
00:01:36sondern die aktuellste Version installiert wird, die meine Kriterien erfüllt – bei mir war das vor einer Woche.
00:01:41Falls Sie dies jemals umgehen müssen, etwa weil ein Sicherheitsproblem mit dem Paket
00:01:45besteht, das Sie installieren möchten, können Sie dies immer noch über die Befehlszeile tun,
00:01:49aber passen Sie bei LLMs auf, denn ich habe Fälle gesehen, in denen LLMs dies einfach zum Umgehen
00:01:54nutzen und trotzdem die neuesten Versionen installieren. Beachten Sie auch,
00:01:59dass NPX und BUNX diese Einstellung nicht respektieren und weiterhin die neueste Version installieren,
00:02:03wofür es in BUN einen offenen Pull-Request zur Korrektur gibt. Während wir bei den Einstellungen sind, lassen Sie uns
00:02:07auch die Installationsskripte für NPM deaktivieren. PNPM und BUN haben dieses Verhalten standardmäßig,
00:02:12sodass es dort nichts einzustellen gibt. Falls Sie es nicht wussten: Wenn Sie ein Paket installieren, darf dieses
00:02:16Paket direkt nach der Installation eigenen Code ausführen. Dies war für legitime Anwendungsfälle
00:02:20gedacht, wie das Kompilieren von nativem Code oder das Herunterladen von Binärdateien, aber das Problem ist,
00:02:26dass fast jeder Supply-Chain-Angriff diese Methode nutzte, um nach der Installation bösartigen Code auszuführen.
00:02:30Falls Sie ein Paket finden, das legitimerweise ein solches Skript benötigt, können Sie es explizit
00:02:34freigeben. Bei PNPM erhalten Sie bei Paketen mit Post-Install-Skripten einen entsprechenden Hinweis,
00:02:39wie hier bei esbuild, und dann können Sie “pnpm approved-builds” verwenden, um die gewünschten Pakete auszuwählen,
00:02:44was Ihre “pnpm workspace allow-builds”-Konfiguration setzt. Sie können auch einfach den
00:02:48allow-build-Flag beim Installationsbefehl nutzen. Wie gesagt, BUN unterbindet diese Installationsskripte
00:02:52standardmäßig, aber es verfügt über eine kuratierte Liste von Paketen, die solche Skripte ausführen dürfen,
00:02:56einschließlich solcher, die ich installiert habe, wie z.B. esbuild.
00:03:00Sie können dies umgehen, indem Sie “trustedDependencies” in Ihrer package.json hinzufügen,
00:03:04sodass nur explizit von Ihnen erlaubte Pakete Post-Install-Skripte ausführen dürfen.
00:03:09Es wird auch erwähnt, dass bei einem leeren Array die Standardliste überschrieben werden sollte,
00:03:12aber das scheint bei mir nicht zu funktionieren; es sieht nach einem Bug aus, den ich auch auf GitHub fand.
00:03:17Der Workaround dafür ist derzeit, einen Wert in die Liste einzutragen, wodurch die Standardliste ignoriert wird.
00:03:21Bei BUN können Sie “bun pm untrusted” ausführen, um zu sehen, welche Pakete Skripte ausführen wollen,
00:03:26aber noch nicht vertrauenswürdig sind, und dann mit “bun pm trust” eines erlauben oder es der
00:03:30“trustedDependencies”-Liste hinzufügen. Sie können Skripte in BUN auch vollständig deaktivieren, indem Sie “install-scripts=false”
00:03:35in Ihrer globalen bunfig setzen. Für NPM ist das schwieriger. Ehrlich gesagt: Nutzen Sie einfach kein NPM,
00:03:40nutzen Sie PNPM. Falls Sie aber aus irgendeinem Grund bei NPM bleiben müssen, können Sie ein ähnliches “Allow-List”-Verhalten
00:03:45durch das “Lavamote's allow-scripts” NPM-Paket erreichen. Auf diese Weise erhalten Sie ebenfalls eine Whitelist in Ihrer
00:03:50package.json. Der dritte Tipp ist, Git-basierte Abhängigkeiten zu blockieren. Bei NPM kann eine Abhängigkeit
00:03:55tatsächlich als Git-URL deklariert werden, wodurch die Registry umgangen wird und sogar eine eigene .npmrc ausgeliefert werden kann,
00:04:01die Lifecycle-Skripte wieder aktiviert. Dies ist einer der Tricks, die beim kürzlichen NPM-Supply-Chain-Angriff
00:04:05auf TanStack verwendet wurden. Sie können dies verhindern, indem Sie “allow-git=none” in Ihrer NPM-Konfiguration setzen,
00:04:10was sie vollständig blockiert. Die andere Option ist, dies auf “root” zu setzen, was Git-basierte
00:04:15Abhängigkeiten nur dann erlaubt, wenn sie in Ihrer Root-package.json deklariert sind, also vermutlich
00:04:19explizit von Ihnen eingestellt. Bei PNPM heißt diese Option “block-exotic-subdependencies”. Wenn dies auf “true” gesetzt ist,
00:04:25können nur direkte Abhängigkeiten – also die, die in Ihrer Root-package.json stehen – exotische
00:04:29Quellen wie Git-Repositorys oder direkte Tarball-URLs nutzen. Diese Option gibt es in Bun noch nicht,
00:04:35aber es gibt einen offenen PR dafür, vielleicht sehen wir das bald. Als Bonus zu den Konfigurationstipps:
00:04:40PNPM hat eine Einstellung namens “trust-policy”, die wir auf “no-downgrade” setzen können. Das bedeutet,
00:04:45dass PNPM fehlschlägt, wenn das Vertrauenslevel eines Pakets im Vergleich zur vorherigen Version gesunken ist.
00:04:50Wenn ein Paket zuvor von einem vertrauenswürdigen Publisher veröffentlicht wurde, jetzt aber nur noch “provenance”
00:04:55oder keine Vertrauensnachweise besitzt, schlägt die Installation fehl. Dies sollte helfen, Angriffe abzufangen,
00:05:00die Wege finden, die üblichen Publishing-Prozesse zu umgehen. Tipp Nummer vier ist wohl der wirkungsvollste:
00:05:04Verwenden Sie ein Tool, das die Pakete bei der Installation prüft, bevor sie
00:05:08überhaupt Ihren Rechner berühren. Dafür haben wir zwei leistungsstarke und komplett kostenlose Tools. Das erste ist
00:05:14Socket (oder MPQ). Sie können dies durch einen Alias für Ihre normalen NPM-, PNPM- oder Bun-Befehle einrichten,
00:05:18sodass bei jeder Installation einige Prüfungen stattfinden. Es scannt auf bekannte
00:05:23Schwachstellen in Snyks Datenbank und markiert Pakete, die weniger als 22 Tage alt sind. Es erkennt
00:05:28Typosquatting – wenn jemand ein Paket wie “express” mit zwei 's' veröffentlicht hat, in der Hoffnung,
00:05:32dass Sie sich vertippen und stattdessen dieses installieren. Es verifiziert die Registry-Signatur und
00:05:37die Build-Provenance. Es warnt Sie bei Paketen mit Pre- oder Post-Install-Skripten und prüft zusätzlich
00:05:41Dinge wie die Download-Zahl, ob es eine Readme, eine Lizenz, eine Repo-URL gibt,
00:05:46und wie die Maintainer-E-Mail lautet – und ob die Domain überhaupt noch registriert ist. Es leistet all das
00:05:51und liefert Ihnen einen interaktiven Bericht, in dem Sie entscheiden können, ob Sie
00:05:55das Paket wirklich installieren wollen. Das zweite Tool ist “Socket Firewall”. Das ist das, das ich verwende,
00:05:59und das Sie ebenfalls für Ihre Paketmanager aliassen. Es unterstützt sogar
00:06:03Technologien außerhalb von JavaScript, wie Python und Rust. Ähnlich wie beim ersten Tool prüft es
00:06:08bei der Installation, blockiert menschlich bestätigte bösartige Pakete und warnt
00:06:12Sie vor KI-erkannten Bedrohungen, die noch nicht menschlich geprüft wurden. Ehrlich gesagt,
00:06:16habe ich mich für Socket Firewall entschieden, weil ich davon zuerst hörte, und ich vertraue Socket,
00:06:21da sie viele bösartige Pakete erkannt haben. Die Angreifer selbst sagten in einem Interview,
00:06:25dass Socket Malware erkennt, bevor das Paket Ihren Rechner erreicht – eine ziemlich gute
00:06:30ein ziemlich gutes Werbeargument für sie, und ich mag auch, dass es mehr als nur JavaScript mit UV, pip und cargo unterstützt.
00:06:35Falls Sie eines davon installieren, sollten Sie den Cache Ihres Paketmanagers leeren,
00:06:38um sicherzustellen, dass jedes installierte Paket von der Firewall geprüft wird. Tipp fünf betrifft Ihre
00:06:42Lock-Dateien. Dort befinden sich die tatsächlichen Download-URLs jedes Pakets, und das Problem ist,
00:06:47dass fast niemand seine Lock-Dateien in einem PR prüft. Wenn jemand einen PR gegen Ihr
00:06:51Repo eröffnet, kann er unbemerkt eine “resolved URL” ändern, damit sie auf ein Paket zeigt, das er kontrolliert,
00:06:56und den passenden Integritäts-Hash setzen, damit nichts auffällt. Bei der nächsten Installation
00:07:01ziehen Sie den Code vom Server des Angreifers. Die gute Nachricht: Wenn Sie PNPM nutzen, sind Sie dagegen
00:07:05geschützt. Es behält diese Tarball-Quellen nicht, die ausgetauscht werden könnten, und installiert auch
00:07:09nichts, was in der Lock-Datei steht, aber nicht in Ihrer package.json deklariert ist. Ich konnte keine
00:07:14konkreten Informationen zu Bun finden, das könnte also noch anfällig sein. Die Lösung, falls Sie kein
00:07:18PNPM nutzen, ist ein Tool namens “lockfile-lint”. Installieren Sie es als Dev-Abhängigkeit; es validiert
00:07:23Ihre Lock-Datei und prüft, ob jedes Paket von einem vertrauenswürdigen Host, wie der NPM-Registry, stammt. Es prüft,
00:07:28ob die resolved URLs mit dem Paketnamen übereinstimmen, und ob die Integritäts-Hashes echt sind.
00:07:32Wenn Manipulation vermutet wird, schlägt die Installation fehl. Tipp 6 ist, aufzuhören,
00:07:37“npm install” in CI und Produktion zu verwenden, sondern stattdessen “clean install” zu nutzen. Der Befehl bei NPM ist
00:07:42einfach “npm ci”, und bei Bun und PNPM nutzen Sie den “frozen-lockfile”-Flag, wobei sie auch CI-Befehle
00:07:47als Alias haben. PNPM nutzt dies standardmäßig, wenn es eine CI-Umgebung erkennt.
00:07:52Der Clean-Install-Befehl installiert exakt das, was in der Lock-Datei steht,
00:07:57und nichts anderes. Wenn Lock-Datei und package.json nicht übereinstimmen, stoppt er sofort mit einem Fehler,
00:08:01statt zu raten und einfach zu installieren. Das sollte verhindern, dass ein Angreifer eine
00:08:05manipulierte Version einschleust. Das funktioniert natürlich nur, wenn Sie Ihre Lock-Datei
00:08:09auch committen – stellen Sie sicher, dass sie in der Versionskontrolle ist und nicht in .gitignore.
00:08:13Als ich als Kind programmieren lernte, dachte ich, man solle diese ignorieren – ich bin froh,
00:08:17dass ich gelernt habe, sie zu committen. Diese sechs Tipps betrafen Konfiguration und Tools, aber es gibt auch
00:08:21Gewohnheiten, mit denen Sie Angriffe vermeiden können. Die erste: Hören Sie auf, blind alles zu aktualisieren.
00:08:25Vielleicht haben Sie schon einmal “npm update” oder ähnliches ausgeführt und alle Abhängigkeiten
00:08:30auf einmal auf den neuesten Stand gebracht – genau darauf hoffen die Angreifer.
00:08:35Gehen Sie die Upgrades durch und fragen Sie sich, warum Sie überhaupt aktualisieren müssen.
00:08:39Die zweite Gewohnheit ist wichtiger denn je: Nutzen Sie weniger Pakete. Jede Abhängigkeit,
00:08:43die Sie hinzufügen, ist eine weitere Angriffsfläche. Die meisten Angriffe verbreiten sich über Abhängigkeiten
00:08:48von Abhängigkeiten, also fragen Sie sich, ob Sie die Bibliothek wirklich brauchen. Häufige Beispiele sind
00:08:53Lodash für Funktionen, die ein kleines Codeschnipsel lösen kann, oder Axios, wo fetch
00:08:58dasselbe leisten kann. Warum das immer relevanter wird: Im Zeitalter des agentischen
00:09:03Codings ist es leicht, KI ein paar Funktionen schreiben zu lassen, statt eine Abhängigkeit zu nutzen.
00:09:08Die dritte Gewohnheit ist das Pinnen von Abhängigkeiten auf exakte Versionen, sodass ein Upgrade eine bewusste
00:09:12Entscheidung ist. Aber Achtung: Das sperrt nur Pakete, die Sie in der package.json wählen,
00:09:17während die Unterabhängigkeiten weiterhin Bereiche nutzen können – genau deshalb zählt die “Cooldown”-Regel aus Tipp 1.
00:09:21Zusammen sollten Sie Ihnen die Sicherheit geben, kein kompromittiertes Paket zu installieren.
00:09:25Sie sind nicht unbesiegbar, aber besser als nichts. Der ultimative Tipp ist,
00:09:29alles in einem gehärteten Dev-Container auszuführen, aber das ist oft zu umständlich,
00:09:34sodass ich doch bei der lokalen Entwicklung lande. Wenn Sie andere Wege kennen,
00:09:38um sich gegen solche Angriffe zu schützen, schreiben Sie es mir in die Kommentare,
00:09:42lassen Sie ein Abo da, und wie immer: Wir sehen uns im nächsten Video.

Key Takeaway

Durch die Kombination von Releas-Verzögerungen, dem Deaktivieren automatischer Installationsskripte und dem Einsatz einer spezialisierten Sicherheits-Firewall wie Socket lässt sich das Risiko von Supply-Chain-Angriffen bei der Arbeit mit NPM, PNPM und BUN nahezu eliminieren.

Highlights

  • Das Festlegen einer Releas-Alter-Begrenzung verzögert die Installation brandneuer Paketversionen und umgeht so die Mehrheit der Supply-Chain-Angriffe.

  • Paketmanager wie PNPM und BUN unterbinden standardmäßig die Ausführung bösartiger Installationsskripte, während für NPM zusätzliche Tools wie Lavamote erforderlich sind.

  • Das Blockieren von Git-basierten Abhängigkeiten verhindert die Umgehung der Registry und das Einschleusen schädlicher Skripte.

  • Tools wie 'Socket' oder 'Socket Firewall' scannen Abhängigkeiten vor der Installation auf Typosquatting, Schwachstellen und bösartige Skripte.

  • Der Einsatz von 'npm ci' oder 'frozen-lockfile'-Flags bei CI-Prozessen erzwingt die exakte Installation der im Lock-File definierten Versionen.

  • Die manuelle Prüfung von Upgrades und die bewusste Reduzierung der Gesamtzahl an Abhängigkeiten minimieren die Angriffsfläche drastisch.

Timeline

Verzögerung von Paketinstallationen

  • Die meisten Supply-Chain-Angriffe werden innerhalb weniger Stunden identifiziert.
  • Releas-Alter-Begrenzungen verhindern die sofortige Installation brandneuer, potenziell kompromittierter Versionen.
  • PNPM setzt ab Version 11 standardmäßig ein Zeitlimit von einem Tag für neue Pakete.

Die Installation von Paketen unmittelbar nach Veröffentlichung macht Entwickler zur primären Zielscheibe. Durch Konfigurationen in .npmrc, pnpm-config.yaml oder bunfig.toml lässt sich definieren, dass nur Versionen installiert werden, die ein gewisses Alter erreicht haben. NPX und BUNX ignorieren diese Einstellungen derzeit und erfordern daher besondere Vorsicht.

Deaktivierung von Installationsskripten

  • Installationsskripte ermöglichen Paketen die Ausführung von eigenem Code direkt nach dem Download.
  • PNPM und BUN unterbinden dieses Verhalten standardmäßig oder bieten explizite Vertrauenslisten.
  • Das Lavamote-Tool ermöglicht ein ähnliches Whitelist-Verhalten für NPM-Nutzer.

Bösartige Akteure nutzen häufig Post-Install-Skripte, um nach der Installation Schadcode auszuführen. Während PNPM und BUN die Ausführung einschränken oder über trustedDependencies steuern, ist für NPM der Einsatz von Sicherheits-Wrappern wie Lavamote notwendig, um unerwünschte Skriptausführungen zu blockieren.

Blockieren gefährlicher Abhängigkeitstypen

  • Git-basierte URLs umgehen die Registry-Prüfung und können eigene Konfigurationsdateien ausliefern.
  • PNPM blockiert exotische Sub-Abhängigkeiten über die Einstellung block-exotic-subdependencies.
  • Die Einstellung trust-policy auf no-downgrade verhindert, dass Pakete in der Vertrauenswürdigkeit sinken.

Git-URLs in Abhängigkeiten stellen ein hohes Sicherheitsrisiko dar, da sie Lifecycle-Skripte reaktivieren können. Die Konfiguration allow-git=none oder die Beschränkung auf Root-Abhängigkeiten minimieren diese Gefahr. Zusätzlich bietet PNPM Sicherheitsmechanismen gegen das Downgrade von Paketen, deren Vertrauensnachweise nachlassen.

Einsatz von Sicherheits-Tools

  • Socket und Socket Firewall prüfen Pakete vor der Installation auf Typosquatting und bösartige Merkmale.
  • Diese Tools unterstützen zusätzlich zu JavaScript auch Python und Rust-Ökosysteme.
  • Die Bereinigung des Caches ist nach der Installation solcher Schutzwerkzeuge erforderlich.

Spezialisierte Firewalls wie Socket analysieren Pakete bereits vor dem Eintreffen auf dem Rechner. Sie scannen Datenbanken auf bekannte Schwachstellen, verifizieren die Herkunft (Provenance) und prüfen Metadaten wie die Aktivität der Maintainer oder die Validität von Readme-Dateien, um bösartige Pakete proaktiv auszusortieren.

Sichere CI-Prozesse und Lock-File-Management

  • Lock-Dateien müssen versioniert werden, um Manipulationen an Download-URLs zu verhindern.
  • Clean-Install-Befehle wie npm ci oder frozen-lockfile verhindern das ungeplante Update von Abhängigkeiten.
  • lockfile-lint validiert die Integrität und den Ursprung der Pakete in der Lock-Datei.

Manipulationen in Lock-Dateien können dazu führen, dass Pakete von Angreifer-Servern geladen werden. Ein Clean-Install-Prozess stellt sicher, dass die Installation exakt dem gesicherten Status des Projekts entspricht. lockfile-lint bietet eine zusätzliche Validierungsebene, um Manipulationen an URLs oder Hashes in der Lock-Datei aufzudecken.

Sichere Entwicklungsgewohnheiten

  • Die manuelle Prüfung von Abhängigkeits-Updates verhindert die automatisierte Übernahme schädlicher Versionen.
  • Die Minimierung der Abhängigkeitsanzahl reduziert die Angriffsfläche massiv.
  • Exaktes Version-Pinning in der package.json zwingt zu bewussten Upgrade-Entscheidungen.

Die Vermeidung unnötiger Bibliotheken durch den Ersatz mit einfachem Code oder KI-generierten Funktionen verkleinert das Risiko von Supply-Chain-Angriffen. Ein bewusster Umgang mit Upgrades statt blindem Aktualisieren schützt vor dem ungewollten Hinzufügen kompromittierter Pakete über Abhängigkeitsketten hinweg.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video