LiteLLM 1.107.0 mit Schadcode: So prüfen Sie, ob Ihre KI-Schlüssel betroffen sind
Am 21. Oktober lag knapp zwei Stunden lang eine verseuchte Version der KI-Bibliothek LiteLLM auf PyPI, auf Docker Hub etwas länger. Sie stiehlt Zugangsdaten und lädt weiteren Code nach. Wir haben unseren eigenen Server durchsucht, zeigen ein kurzes Prüfskript, das ohne Python auskommt, und erklären, warum ein Fund von sitecustomize.py allein noch nichts heißt.
Mit KI erzeugtes Bild. Mehr zur KI-Transparenz
LiteLLM ist eine freie Python-Bibliothek, mit der Programme viele Sprachmodell-Anbieter über eine einheitliche Schnittstelle ansprechen. Es gibt sie auch als Proxy, der die Schlüssel für OpenAI, Anthropic und Co. zentral verwaltet. Genau das macht sie für Angreifer interessant. Wer LiteLLM übernimmt, sitzt an der Stelle, an der in vielen Firmen alle KI-Schlüssel zusammenlaufen.
Am Mittwoch, 21. Oktober, ist genau das passiert. Für knapp zwei Stunden lag auf PyPI, dem zentralen Paketverzeichnis für Python, eine Version 1.107.0, die nicht vom LiteLLM-Team stammte. Sie enthielt laut Hersteller kompilierten Schadcode, der Zugangsdaten stiehlt und Werkzeuge zum Ausführen von fremdem Code nachlädt. Auf Docker Hub war das passende Image noch etwas länger zu haben.
Die meisten Betriebe haben LiteLLM nie bewusst installiert. Das ist der Grund, warum wir darüber schreiben. Bei uns kam es als Abhängigkeit eines anderen Werkzeugs auf den Server, und so geht es vielen.
Was passiert ist
Betroffen sind nach Angaben von LiteLLM ausschließlich diese Pakete:
- PyPI:
litellm==1.107.0, am 21. Oktober von 11:39 bis 13:23 UTC verfügbar, also 13:39 bis 15:23 Uhr deutscher Zeit. - Docker Hub: die Tags
v1.107.0,latest,main-latestundmain-stable, von 11:46 bis 14:20 UTC. - GHCR (die Image-Ablage von GitHub): dieselben vier Tags für
litellm,litellm-databaseundlitellm-non_root, bis 13:51 UTC.
Wer in diesem Zeitraum ein Docker-Image mit latest gezogen oder eine
Python-Umgebung ohne feste Versionsangabe neu gebaut hat, kann den Schadcode
bekommen haben. Kunden der privaten Enterprise-Registry von LiteLLM waren laut
Hersteller nicht betroffen. Auf PyPI ist 1.107.0 inzwischen entfernt, aktuell
ist dort wieder 1.106.2 (Stand 24. Oktober, 7:30 UTC).
Die Sicherheitsforscher von Datadog haben den Schadcode untersucht. Er sucht
nach Cloud-Zugängen, SSH- und Git-Schlüsseln, .env-Dateien,
Sprachmodell-Schlüsseln, Sitzungen von KI-Programmierwerkzeugen und
gespeicherten Browser-Passwörtern. Die Beute geht an litellm[.]dev, eine
Domain, die dem echten Namen zum Verwechseln ähnlich ist. Zusätzlich schaut
eine Hintertür stündlich nach, ob es neuen Code zum Nachladen gibt. Einen
solchen zweiten Teil hat Datadog bisher nicht beobachtet.
Wichtig für die Prüfung: Der Schadcode legt in site-packages die Dateien
cook.pth, cook.py und sitecustomize.py ab. Python führt .pth-Dateien
und sitecustomize.py bei jedem Start aus, ganz gleich, ob ein Programm
LiteLLM überhaupt verwendet. Wer nur den LiteLLM-Ordner löscht, entfernt diese
Dateien nicht.
Wie die Angreifer hineinkamen
Am 23. Oktober hat LiteLLM eine Ursachenanalyse veröffentlicht, die frühere
Vermutungen aus dem ersten Bericht ausdrücklich korrigiert. Der Anfang liegt
fünf Monate zurück. Am 27. Mai landete in einem öffentlichen Repository eine
Konfigurationsdatei mit dem Master-Schlüssel einer Agenten-Plattform, die das
Team selbst betreibt. Der Fehler fiel schnell auf, der Commit wurde
überschrieben, und die offengelegten Schlüssel wurden als zu widerrufen
erkannt. Nur der Master-Schlüssel wurde dann doch nicht widerrufen. Am
10. Oktober nutzte ihn der Angreifer und bekam über eine Schnittstelle dieser
Plattform den GitHub-Zugang eines Organisationsinhabers zurück. Damit las er über Build-Abläufe weitere Schlüssel
von Entwicklern aus, hob am 21. Oktober einen Branch-Schutz auf und ließ die
Veröffentlichung von einem Doppelgänger-Repository bauen, Berri-AI/litellm
statt BerriAI/litellm.
Das ist die eigentliche Lehre, und sie hat mit Python wenig zu tun. Einen Schlüssel aus einem Repository zu löschen ist nicht dasselbe, wie ihn zu widerrufen. Ein einziger Schlüssel, der öffentlich wurde und gültig blieb, hat Monate später die ganze Lieferkette geöffnet. Fast jeder Betrieb, der mit KI arbeitet, hat inzwischen solche Schlüssel: für den Chatbot, für die Automatisierung, für das Programmierwerkzeug der Entwickler. Die Frage, wo sie überall liegen und wann sie zuletzt getauscht wurden, ist unbequem, aber wichtiger als jedes einzelne Update.
Es ist übrigens nicht der erste Vorfall bei LiteLLM in diesem Jahr. Der Hersteller verweist selbst auf einen früheren im März, nach dem er seine Veröffentlichungskette bereits gehärtet hatte.
Wie wir es bei uns geprüft haben
Wir haben heute Morgen unseren Hauptserver durchsucht, auf dem unter anderem unsere Automatisierungen und Testumgebungen laufen. Gefunden haben wir genau eine Python-Umgebung mit LiteLLM, und zwar in Version 1.81.10. Installiert hatten wir es nie selbst. Es kam im Juni als Abhängigkeit eines quelloffenen KI-Programmierwerkzeugs dazu, das die Version fest vorschreibt. Diese feste Angabe hat uns geschützt: Hätte das Werkzeug nur „irgendein LiteLLM“ verlangt, wäre bei einem Neuaufbau am Mittwochnachmittag 1.107.0 gekommen.
Keine Datei cook.pth oder cook.py, nirgends, auch nicht in den Ablagen der
Docker-Images. Keine Marker-Datei in /tmp, weder auf dem Server noch in einem
der 26 laufenden Container. Kein Docker-Image mit LiteLLM und keines mit dem
Digest, den der Hersteller nennt.
Eine Stelle hat uns kurz stutzen lassen. Die Suche nach sitecustomize.py
lieferte 16 Treffer. Keiner davon war Schadcode. 14 sind ein und dieselbe
kleine Datei aus der Python-Grundausstattung von Ubuntu, auf dem Server selbst
und in mehreren Container-Images, die nur die Fehlerberichte des Systems
einbindet. Eine gehört zu einem 3D-Programm, eine zu einem alten eigenen
Testaufbau. Wer nach dem Vorfall sucht, wird solche Dateien fast immer finden.
Ein Treffer heißt deshalb nicht „betroffen“, sondern „ansehen“. Auf Debian und
Ubuntu verrät dpkg -S <pfad>, ob eine Datei zu einem Systempaket gehört.
Verdächtig ist eine sitecustomize.py, die in site-packages neben einer
cook.pth liegt.
Und noch ein Fehler, den wir selbst gemacht haben: Unsere erste Suche nach
cook*.pyc fand Hunderte Dateien, weil das Muster auch auf cookies.pyc und
cookiejar.pyc passt. Im Skript unten steht deshalb das genaue Muster.
Das Prüfskript
Das Skript startet bewusst kein Python, auch kein pip. LiteLLM schreibt in
seiner Meldung, dass jeder Python-Start in einer betroffenen Umgebung den
Schadcode erneut ausführt. Es sucht nur mit find, ls und, wenn vorhanden,
docker. Wir haben es auf Linux getestet, auf unserem Server brauchte es gut
eine Minute. Es braucht Root-Rechte, damit es alle Verzeichnisse sieht.
#!/bin/sh
# Spuren des LiteLLM-Vorfalls vom 21.10.2026 suchen.
# Startet bewusst kein Python: jeder Python-Start würde den Schadcode erneut ausführen.
SKIP='-path /proc -o -path /sys -o -path /dev'
echo "== 1. Installierte LiteLLM-Versionen"
find / \( $SKIP \) -prune -o -type d -name 'litellm-*.dist-info' -print 2>/dev/null
echo "== 2. Dateien des Schadcodes"
find / \( $SKIP \) -prune -o -type f \( -name 'cook.pth' -o -name 'cook.py' \
-o -name 'cook.cpython-*.pyc' \) -print 2>/dev/null
echo "== 3. sitecustomize.py (nicht jeder Fund ist schädlich, ansehen)"
find / \( $SKIP \) -prune -o -type f -name 'sitecustomize.py' -print 2>/dev/null
echo "== 4. Marker in /tmp"
ls -la /tmp/.pc_once_* /tmp/remote_code_loader.lock 2>/dev/null
if command -v docker >/dev/null 2>&1; then
echo "== 5. Docker-Images mit LiteLLM oder dem bekannten Digest"
docker images --digests --no-trunc | grep -i -e litellm -e 1bbcb1443bc9
echo "== 6. Marker in laufenden Containern"
for c in $(docker ps -q); do
docker exec "$c" sh -c 'ls /tmp/.pc_once_* /tmp/remote_code_loader.lock' \
2>/dev/null && echo " ^ Treffer in Container $c"
done
fi
echo "== Fertig"
So lesen Sie das Ergebnis:
Unter Punkt 1 steht litellm-1.107.0.dist-info. Diese Umgebung hatte die
verseuchte Version. Behandeln Sie den Rechner als kompromittiert.
Unter Punkt 2 steht eine Datei. Dasselbe. Der Schadcode war da und lief vermutlich bei jedem Python-Start.
Unter Punkt 4 oder 6 steht eine Datei. Laut Datadog legt der Schadcode
/tmp/.pc_once_… an, nachdem er gelaufen ist, und remote_code_loader.lock
als Sperre gegen einen zweiten Start. Ein Fund heißt also: Er ist gelaufen.
Nichts gefunden. Das ist ein gutes Zeichen, aber kein Beweis. LiteLLM schreibt selbst, dass ein fehlender Fund nicht belegt, dass eine Umgebung sauber ist. Container, die inzwischen gelöscht wurden, und Build-Rechner in der Cloud sieht das Skript nicht. Fragen Sie deshalb auch bei Dienstleistern nach, die für Sie KI-Anwendungen bauen oder betreiben.
Was bei einem Treffer zu tun ist
LiteLLM empfiehlt, betroffene Umgebungen und Images nicht zu reparieren,
sondern neu aufzubauen, mit fester Version, etwa litellm==1.106.2. Dann
kommen die Schlüssel, und zwar von einem sauberen Rechner aus: alle
Anbieterschlüssel, die im LiteLLM-Proxy hinterlegt sind, Master- und virtuelle
Schlüssel, das Passwort der Proxy-Datenbank, die Cloud-Rolle des Rechners und
jedes andere Geheimnis, das in der Umgebung eines Prozesses auf diesem Rechner
stand. Wer in der Cloud arbeitet, sollte zudem in den Protokollen nachsehen, ob
die Zugänge seit dem 21. Oktober von außerhalb benutzt wurden.
Für den Alltag danach bleiben zwei Gewohnheiten, die wenig kosten. Versionen
fest angeben, für Python wie für Docker, und latest aus allem streichen, was
automatisch neu gebaut wird. Und eine Liste führen, wo welche KI-Schlüssel
liegen, damit man sie an einem Vormittag tauschen kann und nicht erst suchen
muss.
Was Sie jetzt tun können
Wenn Sie eigene Server oder Entwicklerrechner mit Python oder Docker haben, lassen Sie das Skript heute laufen. Wenn eine Agentur oder ein Dienstleister Ihre KI-Anwendungen betreibt, fragen Sie konkret, ob LiteLLM irgendwo mitläuft und ob am 21. Oktober neu gebaut wurde.
Wie wir prüfen, was KI-Werkzeuge nachladen, bevor es eingespielt wird, beschreiben wir bei der Update-Schleuse. Was ein Sicherheitstest darüber hinaus findet, steht in KI-Pentest: Was ein Sicherheitstest prüft. Eine zweite Lücke aus dieser Woche, die ganz anders funktioniert, haben wir gestern beschrieben: PHP2Shell.
Wenn Sie wissen wollen, wo in Ihrem Betrieb überall KI-Schlüssel liegen und wer sie tauschen kann, sprechen Sie uns an.
Quellen
Alle abgerufen am 24.10.2026.
- LiteLLM: Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised, 21.10.2026, Stand des Textes 21.10. 20:30 UTC mit Hinweis vom 23.10. (betroffene Pakete, Zeitfenster, Dateien, Digest, Empfehlungen, Hinweis auf den früheren Vorfall im März)
- LiteLLM: The attack chain behind the v1.107.0 LiteLLM release, 23.10.2026 (Ablauf des Angriffs ab 27. Mai)
- Datadog Security Labs: LiteLLM supply chain compromise: What you need to know, 21.10.2026 (Ziele des Schadcodes, Exfiltration, Marker in /tmp, Hintertür)
- PyPI: litellm, aktuelle Version am 24.10.2026, 7:30 UTC
- Eigene Prüfung vom 24.10.2026 (ein Server, alle Dateisysteme und Image-Ablagen, 26 laufende Container)
Stand: 24. Oktober 2026. Der Hersteller untersucht den Vorfall noch und hat seine erste Darstellung bereits einmal korrigiert. Wenn neue Erkenntnisse dazukommen, ergänzen wir den Beitrag.
Häufige Fragen
- Welche LiteLLM-Versionen sind betroffen?
- Laut Hersteller nur litellm 1.107.0 auf PyPI sowie die Docker-Images mit den Tags v1.107.0, latest, main-latest und main-stable auf Docker Hub und GHCR. Auf PyPI war die Version am 21. Oktober 2026 von 11:39 bis 13:23 UTC verfügbar, auf Docker Hub bis 14:20 UTC, auf GHCR bis 13:51 UTC. Der Quellcode-Tag v1.107.0 auf GitHub enthält die schädlichen Dateien nicht.
- Was macht der Schadcode?
- Nach Angaben von LiteLLM stiehlt er Zugangsdaten und lädt Werkzeuge nach, mit denen sich fremder Code ausführen lässt. Datadog Security Labs nennt als Ziele unter anderem Cloud-Zugänge, SSH- und Git-Schlüssel, .env-Dateien, API-Schlüssel für Sprachmodelle, Sitzungen von KI-Programmierwerkzeugen sowie gespeicherte Browser-Passwörter. Die Daten gingen an eine Doppelgänger-Domain von LiteLLM.
- Reicht es, LiteLLM zu deinstallieren?
- Nein. Der Schadcode legt eigene Dateien in site-packages ab, darunter cook.pth und sitecustomize.py, die Python bei jedem Start ausführt, auch wenn LiteLLM gar nicht geladen wird. Datadog schreibt, dass das Löschen des LiteLLM-Ordners diese Dateien nicht entfernt. LiteLLM empfiehlt, Umgebungen und Images neu aufzubauen und alle Schlüssel zu tauschen.
- Warum soll man zur Prüfung kein pip starten?
- Jeder Start von Python in einer betroffenen Umgebung führt cook.pth und sitecustomize.py erneut aus, so steht es in der Meldung des Herstellers. Auch pip ist ein Python-Programm. Deshalb sucht man zuerst mit Bordmitteln des Betriebssystems nach den Dateien.
- Was muss ich tun, wenn ich betroffen bin?
- LiteLLM rät, die Umgebung als kompromittiert zu behandeln, auf 1.106.2 oder eine andere ältere, ausdrücklich angegebene Version festzulegen und neu aufzubauen. Zu tauschen sind alle im LiteLLM-Proxy hinterlegten Anbieterschlüssel, Master- und virtuelle Schlüssel, das Datenbankpasswort und jedes Geheimnis aus der Umgebung der Prozesse auf dem Rechner, und zwar von einem sauberen Gerät aus.
Passend dazu
PHP2Shell: Was Betriebe mit Website, Shop oder eigenem Server jetzt prüfen sollten
InsightsQwen-Vorschaumodell wollte nach Peking hochladen: Warum lokale KI-Agenten einen gesperrten Ausgang brauchen
InsightsBienenratgeber als Trainingsdaten: Was Anthropics neue Studie für Firmen bedeutet, die ein Modell selbst nachtrainieren
InsightsKI-Pentest: Was ein Sicherheitstest bei Chatbots und Agenten prüft, mit 360 eigenen Angriffen