Wichtigste Erkenntnisse
- Sowohl Tippfehler als auch KI-Halluzinationen liefern Angreifern einen verwertbaren Paketnamen, und für beides ist kein Exploit erforderlich.
- Die Herkunft gibt Aufschluss darüber, woher ein Artefakt stammt, nicht aber darüber, ob der dahinterstehende Commit oder das dahinterstehende Konto legitim war.
- Aufmerksamkeit lässt sich nicht skalieren – nutzen Sie daher festgelegte Abhängigkeiten, deterministisches Routing und Skript-Whitelists.
Haben Sie schon einmal darüber nachgedacht, wie lang die Kette der Personen ist, denen Sie jedes Mal vertrauen, wenn Sie ein Paket installieren? Die Person, die den Code geschrieben hat. Die Person, die den Code überprüft hat. Das Repository, in dem er gehostet wird. Der CI-Runner, der ihn um 3 Uhr morgens herunterlädt, ohne dass jemand zusieht. Angreifer sind gut darin, sich in Paket-Ökosystemen umzuschauen, und sie sind mittlerweile sehr geschickt darin, das schwächste Glied in dieser Kette zu finden. Code schneller zu installieren, als ihn jemand überprüfen kann, bringt eine ganze Reihe von Problemen mit sich.
Die meisten Angriffe auf die Software-Lieferkette funktionieren auf diese Weise. Sie müssen keinen Perimeterschutz durchbrechen, sondern nutzen einen vertrauenswürdigen Pfad genau so, wie er ursprünglich vorgesehen war.
Hier ein kurzer Überblick darüber, wie Vertrauen missbraucht wird und was tatsächlich hilft.
Tippfehler in den Paketen
Der älteste Trick, für den man keinen Exploit braucht. Man muss nur schnell tippen und nicht genau hinschauen. Ein Angreifer veröffentlicht ein Paket, bei dem ein Buchstabe oder ein Bindestrich falsch geschrieben ist, und wartet darauf, dass jemand es versehentlich installiert.
Die crossenv Ein bekanntes Beispiel hierfür sind diese Pakete. Im Juli 2017 veröffentlichte ein npm-Nutzer mit dem Namen „hacktask“ rund 40 Pakete, die sich äußerlich ähnelten; besonders auffällig war dabei cross-env ohne Bindestrich. Fehlt dieses eine Zeichen, liest das von Ihnen installierte Programm Ihre Umgebungsvariablen aus und übermittelt sie an einen Server, den der Angreifer kontrolliert.
{
"name": "crossenv",
"scripts": {
"postinstall": "node package-setup.js"
}
}
Der Vorfallbericht von npm benennt das Payload-Skript package-setup.js. Vereinfacht ausgedrückt lief es so ab:
// Simplified illustration of what the script did.
// Reads the environment variables available to the
// install, then sends them to the attacker's server.
const vars = process.env;
sendToAttackerServer(vars);
Auf einem Entwicklerrechner oder einem CI-Runner enthalten diese Variablen häufig Registry-Token, Cloud-Anmeldedaten und Datenbank-Passwörter, weshalb es sich lohnt, sie zu erfassen. npm verzeichnete 679 Downloads für crossenv schätzte jedoch, dass es sich bei höchstens etwa 50 um echte Anlagen und nicht um Spiegel handelte.
Der Grund, warum Typosquatting funktioniert, liegt darin, dass die Lösung nicht in einem Patch besteht. Die eigentliche „Lösung“ besteht darin, aufmerksam zu sein, und wir alle wissen, dass Aufmerksamkeit nicht skalierbar ist. Verlagern Sie die Arbeit also an einen Ort, an dem dies möglich ist: Fixieren Sie Abhängigkeiten, prüfen Sie Änderungen an der Lockfile-Datei ebenso sorgfältig wie Codeänderungen und beziehen Sie die Daten aus einer genehmigten internen Quelle.
Kniebeugen mit KI (Slopsquatting)
„Slopsquatting“ ist derselbe Trick, der auf einem anderen Fehler basiert. Anstelle eines Tippfehlers nutzt er die Tatsache aus, dass ein Programmierassistent ein Paket empfiehlt, das gar nicht existiert, wodurch ein Angreifer die Möglichkeit erhält, diesen Namen zu registrieren, bevor ein echtes Projekt dies tut.
In der USENIX Security 2025-Studie zu „Paket-Halluzinationen“ generierten 16 Modelle 576.000 Code-Beispiele, die auf 2,23 Millionen Pakete verweisen. Bei diesen Tests bezogen sich 19,7 % der Verweise – das sind 440.445 – auf Pakete, die nicht existieren, wobei 205.474 einzigartige, erfundene Namen auftraten. Als die Forscher Prompts erneut ausführten, die bereits zuvor eine Halluzination erzeugt hatten, tauchten 43 % der erfundenen Namen in allen zehn Durchläufen wieder auf, was eine Vorabregistrierung dieser Namen lohnenswert machen kann.
Der Fall „huggingface-cli“ ist ein gutes Beispiel dafür. Der Sicherheitsforscher Bar Lanyado von Lasso Security stellte fest, dass Modelle diesen Namen empfahlen, obwohl es auf PyPI kein solches Paket gab. Daher registrierte er im Dezember 2023 ein leeres Paket. Dieses verzeichnete innerhalb von drei Monaten mehr als 30.000 echte Downloads, und der falsche Installationsbefehl tauchte in der README-Datei eines öffentlichen Forschungs-Repositorys von Alibaba auf.
# What an AI assistant might confidently suggest
pip install huggingface-cli
# What actually installs the official Hugging Face CLI
pip install -U "huggingface_hub[cli]"
Die zweite Option installiert die offizielle huggingface_hub Paket mit seinem CLI-Zusatz. Das erste installiert jede Distribution, die unter einem Namen registriert ist, den ein Modell erfunden hat. Der von Lanyado war absichtlich harmlos. Der von jemand anderem müsste es nicht unbedingt sein. Vergewissern Sie sich also, dass das Projekt existiert, überprüfen Sie den Herausgeber und die Versionshistorie und lassen Sie es genehmigen, bevor es in eine Sperrdatei gelangt.
Verwirrung hinsichtlich der Abhängigkeiten
Eine Abhängigkeitsverwechslung ist ein Fehler bei der Auflösung. Sie tritt immer dann auf, wenn ein Unternehmen private Pakete neben öffentlichen Paketen einsetzt und der Build einen Namen aus mehr als einer Quelle zuordnen kann.
Die Details unterscheiden sich je nach Ökosystem. pip ist das deutlichste Beispiel: Man fügt ihm einen zusätzlichen Index hinzu mit --extra-index-url Es berücksichtigt Kandidaten aus jedem konfigurierten Index und wählt dann die beste Übereinstimmung aus allen aus, was bedeuten kann, dass ein öffentliches Paket mit einer höheren Versionsnummer den Vorrang erhält. npm führt die Auflösung nach Geltungsbereich und konfigurierter Registry durch, anstatt Feeds zusammenzuführen. Daher resultiert die Sichtbarkeit dort in der Regel aus einem internen Namen ohne Geltungsbereich oder einem Proxy, der öffentliche und private Pakete in einer Ansicht zusammenführt, ohne dass dahinter eine Namespace- oder Prioritätsrichtlinie steht.
Alex Birsan demonstrierte das Problem in den Jahren 2020 und 2021, nachdem er festgestellt hatte, dass interne Paketnamen in öffentliche Repositories und Fehlermeldungen durchgesickert waren. Er veröffentlichte unter diesen Namen harmlose Pakete mit sehr hohen Versionsnummern auf npm, PyPI und RubyGems und beobachtete, wie diese in interne Builds von mehr als 35 Unternehmen, darunter Apple, Microsoft und PayPal, aufgenommen wurden, wofür er Bug-Bounties in Höhe von über 130.000 US-Dollar erhielt.
{
"name": "internal-auth-tool",
"version": "99.0.0"
}
Das Gefährliche daran ist nicht das JSON. Es ist ein Build, dessen Konfiguration diesen Namen niemals an eine vertrauenswürdige Quelle bindet. Bei npm solltest du interne Pakete auf einen bestimmten Geltungsbereich beschränken und diesen Geltungsbereich an die private Registry binden.
# .npmrc
registry=https://registry.npmjs.org/
@your-org:registry=https://your-private-registry.example.com/
Dieses Muster ist npm-spezifisch und gilt nur, solange Registry-Routing, Namespace-Zugehörigkeit und Veröffentlichungsberechtigungen übereinstimmen. Ökosysteme ohne Scopes benötigen eine eigene Quellcode-Bindung; für pip bedeutet das, dass --extra-index-url als „Private-First“-Fallback.
Entführte Betreuer
Hier gibt es keine Täuschungsmanöver mehr. Ein Angreifer übernimmt die Kontrolle über das Konto oder den Veröffentlichungsprozess hinter einem Paket, dem Sie bereits vertrauen, und verbreitet ein bösartiges Update über die normale Veröffentlichungsinfrastruktur des Projekts. Ein Vertrauensmissbrauch, kein Code-Exploit.
Am 4. August 2026 ist genau das passiert: keyv sowie die übrigen Mitglieder seiner Caching-Familie. Angreifer hatten sich Zugang zum GitHub-Konto des Betreuers verschafft, bösartige Commits in den Hauptzweig hochgeladen und den projektinternen „Actions“-Workflow dazu gebracht, diese zu kompilieren und zu veröffentlichen. Der Wurm mit dem Spitznamen „ChainDrop“ sammelte alle Anmeldedaten, die in den kompromittierten Umgebungen offengelegt wurden, und nutzte anschließend gestohlene npm-Token, um sich selbst in den Paketen anderer Betreuer erneut zu veröffentlichen. StepSecurity zählte 444 Pakete und 2.212 manipulierte Versionen innerhalb von vier Stunden; andere verzeichneten später höhere Gesamtwerte.
Die manipulierten Releases wiesen eine gültige Herkunftsangabe auf, und dabei handelte es sich nicht um einen Fehler in der Herkunftsangabe. Sie bestätigte zu Recht, dass das Artefakt anhand des projektinternen Workflows aus den angegebenen Eingaben erstellt wurde. Was sie jedoch nicht aussagen kann, ist, ob der vorangegangene Commit legitim war oder ob das dahinterstehende Konto noch immer seinem Eigentümer gehörte.
Viele Teams mussten sich nie entscheiden keyv überhaupt nicht. flat-cache und file-entry-cache unter ESLint fallen und keyv befindet sich darunter.
Skripte vor und nach der Installation
Installationsskripte stellen weniger eine eigenständige Angriffskategorie dar als vielmehr den Ausführungsweg, den einige der anderen nutzen. Ein Paket kann Folgendes deklarieren: preinstall, install, oder postinstall Arbeit, und früher lief das während der Installation, noch bevor jemand auch nur eine Zeile davon gelesen hatte.
Dieser Zeitpunkt ist entscheidend. Das Skript wird mit den Berechtigungen des Entwicklers oder des CI-Runners ausgeführt, während die Installation wie ein Routineschritt aussieht. ChainDrop nutzte einen bösartigen Installations-Hook auf dieselbe Weise.
Das Jahr 2021 ua-parser-js Ein typisches Beispiel hierfür ist „compromise“. Nachdem das npm-Konto des Betreuers gehackt worden war, wurden drei bösartige Versionen mit einem preinstall Ein Hook, der unter Linux einen Kryptowährungs-Miner installierte und unter Windows sowohl den Miner als auch Malware zum Diebstahl von Zugangsdaten. Sie wurden innerhalb von etwa vier Stunden entfernt – für die Maßstäbe der Incident-Response ein schnelles Vorgehen. Das Paket verzeichnete wöchentlich Millionen von Downloads, sodass automatisierte Builds es abriefen, ohne dass jemand den Namen eingeben musste.
{
"scripts": {
"preinstall": "node setup.js"
}
}
Endlich kommt Bewegung in die Zahlungsausfälle. pnpm Seit Version 10 werden keine Skripte zum Erstellen von Abhängigkeiten mehr ohne ausdrückliche Genehmigung ausgeführt, wobei diese Entscheidungen in den aktuellen Veröffentlichungen in einer allowBuilds Karte und npm 12 Blöcke mit Installationsskripten für Abhängigkeiten, die nicht von allowScripts. Machen Sie sich mit dem Verhalten dieser Standardeinstellung vertraut. Das Skript wird mit einer Warnung übersprungen, und die Installation wird dennoch erfolgreich abgeschlossen, sodass eine native Abhängigkeit hinzugefügt werden kann, ohne dass deren Binärdatei jemals erstellt wird. Sobald Sie das Paket freigeben, npm rebuild führt die übersprungenen Installationsschritte aus, und in der CI --strict-allow-scripts führt dazu, dass ein nicht überprüftes Skript zu einer fehlgeschlagenen Installation wird, anstatt dass es stillschweigend nur zur Hälfte ausgeführt wird.
Ältere npm-Versionen sind nicht schutzlos. Sie verhalten sich lediglich standardmäßig anders.
npm install --ignore-scripts
Das ist ziemlich plump. Es führt dazu, dass Pakete, die bei der Installation eigentlich ordnungsgemäß kompiliert werden, nicht mehr funktionieren, und es unternimmt nichts gegen bösartigen Code, der darauf wartet, bis Ihre Anwendung ihn importiert. Betrachten Sie eine explizite Zulassungsliste als die eigentliche Lösung.
Warum das alles immer wieder funktioniert
Keiner dieser Angriffe lässt sich von einer einzelnen Person oder mit einem einzigen Tool beheben. Sie werden schwieriger, wenn ein Team Unklarheiten aus dem Prozess beseitigt: abgegrenzte private Pakete, deterministisches Registry-Routing, festgelegte Installationen anhand einer geprüften Lockdatei, Installationsskripte, die nicht standardmäßig, sondern nur in Ausnahmefällen zugelassen werden, sowie KI-basierte Abhängigkeitsvorschläge, die so lange als ungeprüft gelten, bis sie von jemandem überprüft wurden.
Aber von jedem Entwickler zu erwarten, dass er bei jeder Installation jedes fehlerhafte Paket entdeckt, ist keine Sicherheitsrichtlinie. Das Paket muss schließlich von irgendwoher kommen, und dieser Ort ist Teil Ihrer Sicherheitsgrenzen.
Genau dafür wurde SecureChain entwickelt. Anstatt Artefakte direkt aus einem öffentlichen Register abzurufen, verweisen Sie Ihren Paketmanager auf eine kuratierte Quelle, in der Pakete aus verifizierten Quellcodes in isolierten Umgebungen neu kompiliert, auf Malware überprüft und bei Bekanntwerden neuer CVEs gepatcht werden – mit signierten Builds und Herkunftsnachweisen für Audits. Das Angebot umfasst JavaScript, Python, Java, Go, Rust und PHP, und Entwickler können weiterhin den ihnen vertrauten Paketmanager nutzen.
Wenn es sich bei dem Problem nicht um ein bösartiges, sondern um ein nicht mehr gepflegtes Paket handelt, portiert Endless Lifecycle Support (ELS) Sicherheitskorrekturen auf die von Ihnen bereits verwendeten Versionen zurück, sodass auch nach Ablauf des Upstream-Supports weiterhin Patches bereitgestellt werden.
Meine abschließenden Gedanken
Vertrauen ist eine tragende Säule der modernen Softwareentwicklung, doch was ausgenutzt wird, ist blindes Vertrauen. Angreifer suchen nach Einfallstoren – sei es durch Tippfehler, KI, gekaperte Konten oder die Annahme, dass ein bekanntes Paket immer noch das ist, für das man es gehalten hat. Wir können nicht alles kontrollieren, was im offenen Internet geschieht.
Eine Sache, die Sie kontrollieren können, ist, was letztendlich in Ihrer Umgebung landet. Machen Sie sich klar, wie diese Angriffe funktionieren, sichern Sie Ihre Build-Pipeline ab, verwalten Sie Ihre Registry- und Skriptberechtigungen und richten Sie eine geprüfte Quelle zwischen den öffentlichen Registries und der Produktion ein. Der Code, den Sie ausliefern, sollte genau der Code sein, den Sie ausführen wollten.
