Du tippst npm install ein – vielleicht für ein Nebenprojekt, vielleicht eine Version, die du gerade brauchst. Meistens passiert nichts. Aber genau dieser Moment ist der Ausgangspunkt für eine der größten Sicherheitslücken im modernen Software-Ökosystem: die Lieferkette. Angreifer haben das erkannt. Sie stehlen nicht mehr gezielt einzelne Unternehmen, sie lassen automatisierte Systeme durch die npm-Registry kriechen und übernehmen Pakete wie eine Seuche. Das Team von Evil Martians, ein Entwicklungskollektiv mit mehr als 100 Open-Source-Projekten, hat dazu eine detaillierte Anleitung veröffentlicht. Der Autor beschreibt, wie man im Jahr 2026 ein npm-Paket veröffentlicht, ohne sich selbst zum Opfer zu machen. Die Kernbotschaft vorweg: Die Zeiten, in denen ein geheimer Token auf dem Laptop ausreichte, sind endgültig vorbei.
Warum die „Kleinen“ heute die Hauptziele der Angreifer sind
Der erste Reflex vieler Maintainer ist der Satz: „Niemand will unser kleines Paket hacken.“ Laut dem Autor ist genau das die gefährlichste Annahme. Die Attacken laufen heute semi-automatisch ab. Ein LLM nutzt ein bereits kompromittiertes Paket, um das nächste zu übernehmen, und so weiter. Er erwähnt die Kampagne „Shai-Hulud v2“, bei der an einem einzigen Tag über 500 verschiedene Pakete gehackt wurden. Es funktioniert wie ein Wurm: Es geht nicht darum, die Logik eines Pakets zu verstehen, sondern darum, wie viele Entwickler und deren Maschinen man durch dieses Paket erreichen kann. Dein Paket ist nicht das Ziel, sondern nur ein weiterer Schritt in der Kette.
Selbst ein kleines Utility-Tool mit wenigen tausend Downloads pro Woche ist ein lohnendes Ziel, wenn es als Sprungbrett zu größeren Projekten taugt. Die Kosten für einen Angriff sind durch LLMs enorm gesunken. Du musst also keine perfekte Verteidigung aufbauen, sondern die Kosten für den Angreifer so hoch treiben, dass sein Angriff den Wert der Daten übersteigt. Der Autor stellt klar, dass es keine 100-prozentige Sicherheit gibt. Der Realismus liegt in einer Risikobewertung, die auf echten Angriffsszenarien basiert, nicht auf Sicherheitstheater.
Das Fundament: Trusted Publisher statt NPM_TOKEN
Wer heute noch ein NPM_TOKEN als Geheimnis in der CI-Datei liegen hat, trägt laut dem Autor einen schlafenden Einbrecher im Haus. Ein gestohlener Token ist vergleichbar mit einem Universalschlüssel für dein gesamtes npm-Konto. In den Shai-Hulud-Kampagnen war genau das die bevorzugte Methode: Malware im node_modules liest die Token-Dateien und pusht sie an den Angreifer. Die Lösung heißt Trusted Publisher. Dabei verbindet sich npm direkt mit deiner GitHub-Organisation und dem Repository. npm fragt bei GitHub nach, ob der aktuelle CI-Lauf tatsächlich von dir stammt, und vergibt temporäre, kurzlebige Zugangsrechte.
Der Autor beschreibt die Einrichtung als unkompliziert: In den Einstellungen deines Pakets auf npmjs.com legst du einen Trusted Publisher an, wählst GitHub als Provider und trägst den Repository-Namen sowie den Workflow-Dateinamen ein. Wichtig ist, nur npm stage publish zu erlauben – das wird später noch relevant. Zusätzlich sollte der optionale Token-Zugriff in den npm-Einstellungen komplett deaktiviert werden. Das beste Geheimnis ist einfach keines. Der Vorteil liegt auf der Hand: Selbst wenn der Angreifer die komplette CI-Umgebung übernimmt, findet er dort keinen Token, den er stehlen kann.
Die CI-Kette zur Festung machen: SHA-Pinning und Workflow-Linting
Doch auch ohne Token bleibt ein Angriffsvektor offen: die Drittanbieter-Actions in deinen GitHub-Workflows. Viele nutzen Tags wie @v7. Ein Tag ist nicht unveränderlich. Ein angegriffener Maintainer könnte den Tag verschieben und deine nächste CI-Ausführung mit bösartigem Code infizieren. Das passiert öfter, als dir lieb ist. Der Autor berichtet vom Fall tj-actions/changed-files, wo genau das geschah. Die Lösung ist simpel und genial zugleich: Verwende statt Tags den vollständigen SHA-Commit-Hash der Action, etwa @9c091bb2…. Das wirkt wie ein Lockfile für deine CI-Abhängigkeiten – einmal geprüft, bleibt es bei dieser exakten Version.
Um diese Hashes zu verwalten, nennt der Autor drei Tools: Dependabot, pinact und actions-up. Seine Empfehlung lautet auf actions-up, weil es einen eingebauten Cooldown besitzt und sich sauber in ein npm-Projekt integrieren lässt. Zusätzlich rät er zu einem Workflow-Linter. CodeQL aus dem GitHub-Setup kann erkennen, wenn ein Angreifer versucht, deine Workflows zu missbrauchen. Für mehr Regeln eignet sich zizmor, ein Linter, der nur auf GitHub Actions spezialisiert ist. Wer hier spart, läuft laut dem Autor Gefahr, die eigene Release-Pipeline zum Einfallstor zu machen. Und noch ein Hinweis, der oft übersehen wird: Nachdem du einen Sicherheitsfehler gefixt hast, solltest du alle alten Branches löschen. Das Nx-Team hatte einen Fehler in einem alten Branch korrigiert, aber der alte Branch existierte noch – der Angreifer eröffnete genau dort einen Pull-Request.
Der menschliche Faktor: Staged Publishing und npm Provenance
Bisher klingt alles nach Automatisierung. Doch der Autor spricht einen wichtigen Punkt an: Er mochte npm Provenance anfangs nicht, weil eine reine CI-Veröffentlichung weniger sicher ist als eine manuelle mit Hardware-2FA. Denn ein kompromittiertes CI-System kann dein Paket veröffentlichen, während du schläfst. Die Lösung liegt in einer Kombination aus beidem, genannt „Staged Publishing“. Hier verläuft die Pipeline zweistufig. Im ersten Schritt führt die CI den Build und einen Testlauf durch, publiziert das Paket aber nur als Bühnen-Entwurf. Dazu nutzt sie den Befehl npm stage publish anstelle von npm publish. Im zweiten Schritt musst du selbst, mit deinem Hardware-2FA-Token, das Paket freigeben. Das geschieht über die npm-Webseite im Menüpunkt „Staged Packages“ oder per CLI mit npm stage approve.
Damit bekommst du die Bequemlichkeit von CI-Publishing und zugleich die Sicherheit einer manuellen Kontrolle. Ein pragmatischer Ansatz, der den Hauptnachteil von reinen CI-Release-Pipelines behebt. Wichtig ist: npm stage publish erlaubt dir, das Paket vor der Freigabe zu prüfen. Das Problem dabei: npmjs.com zeigt keinen Diff an. Du könntest also übersehen, dass dein Build-Schritt bösartigen Code eingefügt hat. Deshalb empfehlen die Autoren einen Dienst namens drydock. Dort erstellst du ein Konto, hinterlegst einen Read-Only-Token, und drydock meldet sich per E-Mail, sobald ein neues Stage-Paket auftaucht. Du siehst den Diff, prüfst die Änderungen und gibst das Paket dann erst auf npmjs.com mit deiner Hardware-2FA frei.
Die restliche Ausrüstung: Tag-Regeln, Cooldowns und Paketmanager
Ein weiterer Baustein betrifft die Rollenverteilung auf GitHub. In den Repository-Einstellungen lässt sich per Ruleset festlegen, dass nur Administratoren neue Tags erstellen dürfen. So verhinderst du, dass ein kompromittierter Entwickler-Account heimlich einen alten Tag wie v3 überschreibt und damit das nächste Release sabotiert. Der Autor schlägt außerdem eine Abkühlphase von drei Tagen vor, bevor du eine neue Version deines Pakets verwendest. Das gibt dir Zeit, mögliche Schadenskampagnen zu beobachten, bevor sie dich erreichen.
Ein Punkt, der fast nebenbei erwähnt wird, aber enorm effektiv ist: der Wechsel auf moderne Paketmanager. npm 12, pnpm 10, yarn 4.14 oder bun führen standardmäßig keine postinstall-Skripte der Abhängigkeiten aus. Diese Skripte sind ein beliebter Vektor für Malware, da sie bei der Installation sofort und ohne Zutun des Entwicklers ausgeführt werden. Wenn dein Paketmanager diese Skripte ignoriert, entfernst du eine der gefährlichsten Angriffsflächen in deiner gesamten Entwicklungsumgebung. Zum Abschluss der Konfiguration zeigt der Autor ein Beispiel-Workflow-File publish.yaml. Er rät explizit, auf einen Build-Schritt zu verzichten, wenn es möglich ist – etwa bei einer reinen JavaScript-Bibliothek. Je weniger Verarbeitungsschritte zwischen deinem Quellcode und dem endgültigen npm-Paket liegen, desto geringer ist die Chance, dass dort unerkannt Code eingeschleust wird.
Die nüchterne Einordnung: Wofür das alles gut ist
Was bleibt nach der ganzen Umstellung? Sicherheit ist keine Show. Der Autor betont, dass ein grüner Check beim npm-Provenance-Badge nicht bedeutet, dass dein Paket sicher ist – es bedeutet nur, dass es aus einer bestimmten Pipeline kommt. Es verrät nichts darüber, ob diese Pipeline sauber war. Trotzdem ist das mehr als Theater. Es erhöht die Kosten für den Angreifer enorm. Jeder Schritt, den du hier gehst – Trusted Publisher, SHA-Pinning, Staged Publishing, Cooldown – macht dein Paket zu einem unattraktiven Ziel. Und diese Arbeit lohnt sich auch aus Marketing-Sicht: Immer mehr Unternehmen ziehen bei der Bewertung einer Open-Source-Bibliothek den Sicherheits-Score auf npmjs.com heran.
Der Autor schließt mit einem Blick in die Zukunft: Wenn die eigentliche Programmierarbeit zunehmend von LLMs übernommen wird, wandert der menschliche Fokus zu Absicherung und Kontrolle. Grundlegende Sicherheitskenntnisse werden dann zur Kernkompetenz jedes Entwicklers. Wer seiner Lieferkette nicht vertraut, kann auch seinen eigenen Code nicht vertrauen. Behandle deine Release-Pipeline also wie ein hochwertiges Bankfach: Der Schlüssel ist physisch bei dir, die Transaktion wird überwacht, und du selbst bist der letzte Kontrollpunkt. Genau so – und nicht anders – wird sauberes npm-Publishing im Jahr 2026 aussehen.
Quelle: evilmartians.com
