Am 21. Oktober um 11:39 UTC wurden sieben Wheels von litellm==1.107.0 auf PyPI hochgeladen. Jedes enthielt kompilierte Malware: einen Credential-Stealer, der zusätzlich Werkzeuge für Remote-Code-Ausführung nachlud. Acht Minuten später zeigten die Docker- und GHCR-Tags latest, main-latest und main-stable auf denselben vergifteten Build.
Um 13:23 war das Paket entfernt. Um 14:20 waren die Container-Tags umgebogen.
Zwei Stunden. Lang genug, damit ein CI-Runner es installiert, ein Laptop es importiert und ein paar API-Schlüssel das Gebäude verlassen.
Wenn du irgendetwas mit KI baust, ist das jetzt dein Stack. Keine Metapher, keine Vendor-Story aus einer fremden Branche. LiteLLM ist der Proxy, den viele Teams vor OpenAI, Anthropic und Bedrock setzen, um eine API, einen Schlüssel und eine Rechnung zu haben. Wird er kompromittiert, erbt die Kompromittierung jeden Provider-Schlüssel, den du darin gespeichert hast.
Der Teil, den alle überspringen
Der interessante Fehler ist nicht die Malware. Es ist die Frage, wie das Release signiert wurde.
LiteLLM hat das Jahr nach dem Vorfall im März genutzt, um die Pipeline zu härten: Releases aus einem privaten Repo, Trusted GitHub Publishers, unveränderliche Tags, signierte Images, ein Publishing-Laptop, der im Büro eingeschlossen ist. Nach eigener Darstellung hat der Angreifer keinen dieser Kontrollpunkte gebrochen. Er nutzte Zugangsdaten, die bereits berechtigt waren, sie zu bedienen:
- Ein GitHub-CLI-OAuth-Token eines Entwicklers, das Workflows ausführen konnte.
- Ein Token eines GitHub-Organization-Owners, das Branch Protection aushebeln und einen Workflow-Change per Force-Push durchsetzen konnte.
- Die Zugangsdaten eines dritten Kontos, mit denen nach der Veröffentlichung die Workflow-Logs gelöscht wurden.
Woher kam der erste Token? Aus einem Log.
LiteLLMs Untersuchung ergab, dass Claude Code manchmal den GitHub-CLI-OAuth-Token eines Nutzers in einen Antwort-Body einbettet. Ihr Proxy protokollierte Antwort-Bodys. Der Token landete im Log eines internen LiteLLM-Deployments, das aus dem Internet erreichbar war. Ein Angreifer mit einem Konto auf diesem Deployment las die Logs, nahm den Token und lief in die Release-Pipeline.
Lies die Kette noch einmal. Niemand hat phisht. Niemand hat ein Passwort geknackt. Ein Coding-Assistent, den heute viele Teams einsetzen, schrieb ein gültiges Credential in eine Antwort, in die es nie gehörte, die Observability-Schicht schrieb es auf Platte, und die Platte war erreichbar.
Warum das kein LiteLLM-Problem ist
Das Muster gilt diese Woche für jeden KI-Stack in einem normalen Unternehmen:
- Tokens wandern durch den Modellkontext. Agenten kleben Header, Umgebungsvariablen und CLI-Ausgaben in Antworten. Alles in einer Antwort kann protokolliert, gecacht, getraced oder evaluiert werden.
- Proxies sammeln Credentials. Ein KI-Gateway hält die Schlüssel für jeden Provider, an den es routet. Funktional ist es ein Secrets-Manager mit HTTP-Oberfläche.
- Agenten erben die Entwickleridentität. Läuft dein Assistent mit deinem
gh-Login und deinen Repo-Rechten, ist ein gestohlener Token nicht "ein Token", sondern du. - Shadow-Deployments haben keinen Besitzer. Ein "harmlos benanntes Benutzerkonto" auf einem öffentlich erreichbaren internen Deployment ist der normalste Fund der Welt und der teuerste.
Dieselbe Woche brachte eine zweite, unabhängige Warnung. Railway teilte mit, ein unbefugter Dritter habe möglicherweise auf verschlüsselte Umgebungsvariablen zugegriffen und bei einigen den entschlüsselten Inhalt erhalten, und erklärte, die Kampagne ziele auf Plattformfirmen, um KI-Inference-Provider zu erreichen. Man bat alle Kunden, sämtliche Schlüssel zu rotieren.
Zwei Anbieter, eine Woche, dieselbe Asset-Klasse: Zugangsdaten direkt neben KI-Infrastruktur.
Die vier Kontrollen, die diese Kette gebrochen hätten
Nichts davon ist exotisch. Jedes Glied stirbt an etwas Langweiligem.
1. Behandle Logs als Credential-Oberfläche. Redigiere beim Schreiben, nicht beim Lesen. Kann ein Antwort-Body einen Bearer-Token, einen OAuth-Token oder einen Connection-String enthalten, muss der Logger filtern, bevor es im Speicher landet. Halte die Aufbewahrung für Prompts und Antworten kurz und behandle jeden Log-Store, der je Tokens enthielt, als Rotationsereignis.
2. Trenne "veröffentlichen" von "aushebeln". Das Release-Gate existierte und funktionierte. Was versagte: Dieselbe Klasse von Identität konnte es abschalten. Branch Protection, die ein Org-Owner mit einem Token deaktiviert, ist ein Vorschlag mit Audit-Trail. Publishing-Rechte gehören hinter hardwaregebundene, kurzlebige Credentials und einen zweiten Menschen, und nichts anderes sollte den Workflow bearbeiten können, der sie nutzt.
3. Pinnen, dann belegen. pip install litellm ohne Version ist die Anweisung, das zuletzt veröffentlichte Paket auszuführen. Pinne exakte Versionen und Digests für Images. Und geh weiter: Ein Lockfile ist eine Behauptung, kein Beweis. Erzeuge ein SBOM, prüfe Signaturen wo vorhanden und vergleiche, was eine neue Version in deiner Umgebung tatsächlich tut.
4. Gehe von Exposition aus, damit die Reaktion eine Checkliste ist und keine Debatte. LiteLLMs eigene Anleitung ist das Modell: Wenn du es installiert hast, betrachte die Umgebung als kompromittiert. Lösche die Dropper-Dateien, beende den Daemon mit /tmp/remote_code_loader.lock, rotiere die Instance-Role, jeden Provider-Schlüssel in der Proxy-Datenbank, Master- und Virtual-Keys sowie die DATABASE_URL. Prüfe danach CloudTrail auf GetCallerIdentity aus der Instance-Role zum Installationszeitpunkt und auf die Nutzung dieser Credentials von außerhalb deiner Infrastruktur.
Was diese Woche zu tun ist
Wenn du einen LiteLLM-Proxy betreibst, erledige das vor Montag:
pip show litellmauf jedem Host, Image und CI-Runner. Alles auf 1.107.0 gilt als kompromittiert, nicht als "möglicherweise kompromittiert".- Suche im Dateisystem nach
litellm-1.107.0.dist-info,cook.pthundsitecustomize.py. Abwesenheit beweist nichts, Anwesenheit bestätigt die Exposition. - Rotiere Provider-Keys, Master- und Virtual-Keys, das Datenbankpasswort und die Cloud-Instance-Role.
- Wenn du Railway nutzt, rotiere Umgebungsvariablen und Credentials für private Registries.
- Prüfe, wer deine Release-Workflows bearbeiten kann, und entferne Organization-Owner-Tokens aus allem Automatisierten.
Wenn du lieber jemanden mit durch den Stack gehen lässt: Genau das machen wir als Festpreis-Projekt. Credential-Inventur, Rotation und die Pipeline-Kontrollen, die den nächsten Fall stoppen. Schreib an [email protected].
Die unbequeme Erkenntnis
Die bequeme Geschichte ist, dass ein Anbieter eine schlechte Woche hatte. Die genaue Geschichte ist, dass der moderne KI-Stack drei Dinge zusammensetzt, die nie zusammen gedacht waren: ein Modell, das jeden Token in seinem Kontext bereitwillig wiederholt, ein Proxy, der die Schlüssel zu allem speichert, und Release-Tooling, das einem Credential mehr vertraut als einem Menschen.
Das Malware-Fenster waren zwei Stunden. Die Credential-Spur, die es hinterlässt, wird länger leben. Repariere die Spur.