Wie ein kompromittierter Sicherheitsscanner zum Schlüssel für eine Backdoor in LiteLLM wurde
24. März 2026
0 Min. LesezeitAm 24. März 2026 wurde festgestellt, dass zwei Versionen des Python-Pakets litellm auf PyPI Schadcode enthielten. Die Pakete (Versionen 1.82.7 und 1.82.8) wurden von einem als TeamPCP bekannten Angreifer veröffentlicht, nachdem dieser sich über eine frühere Kompromittierung von Trivy – einem Open-Source-Sicherheitsscanner in der CI/CD-Pipeline von LiteLLM – die PyPI-Zugangsdaten des Maintainers beschafft hatte.
Die schädlichen Versionen waren etwa drei Stunden lang verfügbar, bevor PyPI das Paket unter Quarantäne stellte. LiteLLM wird täglich rund 3,4 Millionen Mal heruntergeladen.
Snyk verfolgt diesen Vorfall. Wenn Sie Snyk-Kunde sind, haben Sie möglicherweise bereits das In-App-Warnbanner gesehen und eine E-Mail-Benachrichtigung erhalten. Der Schwachstelleneintrag lautet SNYK-PYTHON-LITELLM-15762713. Statusmeldungen finden Sie im Snyk Trust Center.
Kurzfassung
Betroffenes Paket |
|
Betroffene Versionen | 1.82.7, 1.82.8 |
Sichere Versionen | ≤ 1.82.6 |
Snyk-ID | |
Erstmals erkannt | 10:39 UTC, 24. März 2026 (Upload von 1.82.7) |
PyPI-Quarantäne | \~13:38 UTC, 24. März 2026 |
Angreifer | TeamPCP (auch bekannt als PCPcat, Persy_PCP, ShellForce, DeadCatx3) |
Angriffsvektor | Supply-Chain-Angriff: kompromittierte PyPI-Publisher-Zugangsdaten über eine manipulierte Trivy-GitHub-Action in der LiteLLM-CI/CD-Pipeline |
Payload-Typ | Dreistufig: Zugangsdaten-Diebstahl + verschlüsselte Datenexfiltration + persistente Backdoor + Kubernetes-Wurm |
Exfiltrations-Domain |
|
MITRE ATT\&CK | T1546.018 (Python-Startup-Hooks), T1003 (Zugangsdaten-Dumping), T1610 (Container bereitstellen) |
Wichtige Ereignisse
Zeit (UTC) | Beleg | Ereignis |
|---|---|---|
Ende Februar 2026 |
| |
19. März, 17:43 UTC | Die GitHub-Action-Tags von Trivy | |
23. März, 12:58 UTC | Endor Labs (vor dem Löschen erfasste PyPI-Metadaten) | Checkmarx-KICS-GitHub-Action kompromittiert; C2-Domain |
24. März, 10:39 UTC | Endor Labs (vor dem Löschen erfasste PyPI-Metadaten) | Schädliches |
24. März, 10:52 UTC | Schädliches | |
24. März, 11:48 UTC | FutureSearch (Callum McMahon) eröffnet ein Offenlegungs-Issue | |
24. März, 12:36 UTC | HN-Thread veröffentlicht; erreicht 324 Punkte | |
24. März, \~12:44 UTC | GitHub-Issue #24512 (aus Kommentarzeitstempeln ersichtlich) | Bots überfluten Issue #24512 mit Kommentaren; das Issue wird über das kompromittierte Maintainer-Konto geschlossen |
24. März, 13:03 UTC | FutureSearch (Update mit Zeitstempel) | FutureSearch bestätigt die Schließung des Issues und den Bot-Spam |
24. März, 13:48 UTC | Neues, unverfälschtes Tracking-Issue eröffnet | |
24. März, 15:09 UTC | LiteLLM-Maintainer bestätigt, dass alle GitHub-, Docker- und PyPI-Schlüssel rotiert wurden; Maintainer-Konten wurden neuen Identitäten zugeordnet | |
24. März, 15:27 UTC | Kompromittierte Versionen gelöscht; Paket auf PyPI aus der Quarantäne entlassen |
Wie der Vorfall entdeckt wurde
Callum McMahon von FutureSearch testete ein Cursor-MCP-Plugin, das litellm als transitive Abhängigkeit einband. Kurz nach dem Start von Python reagierte sein Rechner aufgrund von RAM-Erschöpfung nicht mehr. Er führte dies auf das neu installierte litellm-Paket zurück und fand litellm_init.pth, eine doppelt Base64-kodierte Datei mit 34.628 Byte in site-packages/.
Die RAM-Erschöpfung war eine Nebenwirkung der Payload und kein beabsichtigtes Merkmal. Der .pth-Mechanismus wird bei jedem Start des Python-Interpreters ausgelöst. Da die Payload einen neuen Python-Unterprozess startet und dieser neue Prozess ebenfalls die Ausführung von .pth auslöst, entstand unbeabsichtigt eine Fork-Bombe. McMahon veröffentlichte seine Erkenntnisse auf futuresearch.ai. Innerhalb einer Stunde verbreitete sich die Meldung auf r/LocalLLaMA, r/Python und Hacker News.
Die Angriffskette
Der Angriff auf LiteLLM begann fünf Tage zuvor mit Trivy.
19. März: Die Angreifer änderten Git-Tags im Repository der trivy-action-GitHub-Action so, dass sie auf eine schädliche Version (v0.69.4) mit derselben Payload zum Diebstahl von Zugangsdaten und derselben Exfiltrationsinfrastruktur wie bei späteren Angriffen verwiesen. (Ausführliche Informationen zur Trivy-Kompromittierung finden Sie in Snyks Berichterstattung zur Supply-Chain-Kompromittierung der Trivy-GitHub-Actions.)
23. März: Dieselbe Infrastruktur wurde bei einem separaten Angriff auf Checkmarx KICS (Keep Infrastructure as Code Secure) eingesetzt. Die C2-Domain checkmarx.zone, die das Sicherheitsunternehmen Checkmarx imitiert, wurde bei dieser Operation registriert und aktiviert.
24. März: Die CI/CD-Pipeline von LiteLLM führte Trivy als Teil des Build-Prozesses aus und bezog es ohne festgelegte Version über apt. Die kompromittierte Action exfiltrierte das PYPI_PUBLISH-Token aus der GitHub-Actions-Runner-Umgebung. Mit diesen Zugangsdaten veröffentlichten die Angreifer litellm 1.82.7 um 10:39 UTC und 1.82.8 um 10:52 UTC, beide mit schädlichen Payloads.

Erste Stellungnahme eines LiteLLM-Maintainers auf Hacker News.
Zwei Bereitstellungsmechanismen
Die beiden schädlichen Versionen nutzten unterschiedliche Einschleusungstechniken:
1.82.7 (Quellcode-Injektion): Die Payload war Base64-kodiert und direkt in litellm/proxy/proxy_server.py eingebettet. Sie wird ausgeführt, sobald etwas litellm.proxy importiert – dem standardmäßigen Importpfad für den Proxy-Server-Modus von LiteLLM.
1.82.8 (.pth Datei): Diese Version fügte litellm_init.pth zu site-packages/ hinzu. Der .pth-Mechanismus wird bei jedem Start des Python-Interpreters ohne erforderlichen Import ausgelöst – auch beim Start von Python durch pip, python -c oder den Sprachserver einer IDE.
Die .pth-Datei ist korrekt in der RECORD-Datei des Wheels aufgeführt und besteht daher die Hash-Prüfung von pip. Das Paket besteht alle standardmäßigen Integritätsprüfungen, da der Schadcode mit legitimen Zugangsdaten veröffentlicht und nicht nachträglich eingeschleust wurde. Eine ausführliche Erklärung dieser Angriffsart finden Sie in Kompromittierung eines legitimen Pakets auf Snyk Learn.
Die CPython-Maintainer haben das Sicherheitsrisiko von .pth-Startup-Hooks in Issue #113659 anerkannt, aber es wurde kein Patch angewendet. Diese Technik entspricht MITRE ATT\&CK T1546.018 (Python-Startup-Hooks).
Die dreistufige Payload
Stufe 1: Informationsbeschaffung
Das Skript sammelt:
Systemdaten: Hostname, Umgebungsvariablen, laufende Prozesse, Netzwerk-Routing, aktuelle Authentifizierungsprotokolle aus
/var/log/auth.logZugangsdaten: private SSH-Schlüssel,
.env-Dateien, Git-Zugangsdaten, API-Schlüssel aus dem Shell-Verlauf, Slack- und Discord-Webhook-Tokens, CI/CD-Konfigurationen (Jenkins, Travis CI, Terraform), Passwort-Hashes aus/etc/shadowCloud-Zugangsdaten: AWS-Zugangsdaten und -Konfiguration, GCP- und Azure-Service-Account-Dateien, Cloud-Metadaten über direkte IMDS-Abfragen, AWS Secrets Manager und SSM Parameter Store (mit vollständig implementierter IMDSv2-Signierung im Skript)
Container und Orchestrierung: Docker-
config.json(Registry-Zugangsdaten), Kubernetes-kubeconfig-Dateien, Service-Account-Tokens, Secrets und ZertifikateKryptowährungen: Bitcoin-, Ethereum-, Solana-, Cardano- und Monero-Wallet-Dateien und Seed-Phrasen sowie Konfigurationen von Ledger-Hardware-Wallets

Ausschnitt des dekodierten Schadcodes mit strukturierter Iteration und Sammlung von Secrets in verschiedenen Verzeichnissen
Stufe 2: Verschlüsselung und Exfiltration
Die gesammelten Daten werden vor der Übertragung verschlüsselt:
Ein 32-Byte-AES-256-Sitzungsschlüssel wird mit
openssl randgeneriertDie Daten werden mit AES-256-CBC verschlüsselt (PBKDF2-Schlüsselableitung)
Der Sitzungsschlüssel wird mit einem fest kodierten 4096-Bit-RSA-Public-Key verschlüsselt (OAEP-Padding)
Alles wird in
tpcp.tar.gzgebündeltDas Bundle wird per POST über
curlanhttps://models.litellm.cloud/gesendet
models.litellm.cloud unterscheidet sich von der legitimen Domain litellm.ai und wurde am 23. März registriert – einen Tag vor der Veröffentlichung der schädlichen Pakete.
Der RSA-Public-Key in dieser Payload ist identisch mit dem in den Trivy- und KICS-Payloads. Wiz-Forschende bestätigten diese Übereinstimmung bei allen drei Operationen. Dies ist der stärkste einzelne technische Beleg für die Zuordnung.
Während der Exfiltration erstellte temporäre Dateien: session.key, payload.enc, session.key.enc und tpcp.tar.gz im temporären Systemverzeichnis.

Entschärfte Darstellung des Schadcodes. Der Archivname tpcp.tar.gz ist ein durchgängiges Erkennungsmerkmal bei den Trivy-, KICS- und LiteLLM-Operationen.
Stufe 3: Persistenz und laterale Bewegung
Lokale Persistenz:
Schreibt ein Python-Backdoor-Skript nach
~/.config/sysmon/sysmon.py(oder/root/.config/sysmon/sysmon.py)Erstellt einen systemd-Benutzerdienst unter
~/.config/systemd/user/sysmon.servicemit der Beschreibung „System Telemetry Service“Registriert und aktiviert ihn:
systemctl --user daemon-reload && systemctl --user enable --now sysmon.service
Das Persistenzskript fragt alle fünf Minuten https://checkmarx.zone/raw nach einer URL ab, lädt die Datei nach /tmp/pglog herunter, macht sie ausführbar und startet sie als Hintergrundprozess. Der Status wird in /tmp/.pg_state gespeichert. Zum Zeitpunkt der Analyse lieferte der Endpunkt YouTube-URLs zurück; der Betreiber kann jederzeit stattdessen aktive Payloads ausliefern.
Laterale Bewegung in Kubernetes: Findet das Skript ein Kubernetes-Service-Account-Token unter dem Standard-Mount-Pfad, liest es alle Secrets in sämtlichen Namespaces aus. Anschließend versucht es, in kube-system auf jedem Node einen privilegierten Pod bereitzustellen, der alpine:latest verwendet. Diese Pods mounten das Host-Dateisystem und installieren die sysmon-Backdoor auf dem zugrunde liegenden Node.
Die schädlichen Pods heißen node-setup-{node_name} (der Node-Name wird auf 35 Zeichen gekürzt); der Container heißt setup.
Über TeamPCP
TeamPCP (laut Wiz Threat Center auch bekannt als PCPcat, Persy_PCP, ShellForce und DeadCatx3) ist mindestens seit Dezember 2025 aktiv. Der Angreifer betreibt Telegram-Kanäle unter @Persy_PCP und @teampcp und fügt Payloads die Zeichenfolge „TeamPCP Cloud stealer“ hinzu. Wiz hat die gesamte Kampagne verfolgt (Wiz Threat Center; Wiz-Blog; ramimac.me).
Die LiteLLM-Kompromittierung ist Phase 09 einer laufenden Kampagne. Bei allen Operationen kommt dieselbe Infrastruktur zum Einsatz: dasselbe RSA-Schlüsselpaar, derselbe Name für das Bundle tpcp.tar.gz und GitHub-Repositories mit dem Präfix tpcp-docs, die als Dead-Drop-C2-Staging dienen. Alle drei Domains dieser Operation nutzen denselben Registrar (Spaceship, Inc.) und Hosting-Anbieter (DEMENIN B.V.).
Der Angreifer hat außerdem CanisterWorm eingesetzt, das das Internet Computer Protocol (ICP) als C2-Kanal nutzt. ICP-Canister können weder von Domain-Registraren noch von Hosting-Anbietern abgeschaltet werden. Sicherheitsforschende von Aikido dokumentieren dies als ersten beobachteten Einsatz von ICP als C2-Mechanismus in einer Supply-Chain-Kampagne.
Eine Komponente namens hackerbot-claw nutzt einen KI-Agenten (openclaw) zur automatisierten Auswahl von Angriffszielen. Aikido-Forschende dokumentierten dies als einen der ersten Fälle, in denen ein KI-Agent operativ bei einem Supply-Chain-Angriff eingesetzt wurde.
Unterdrückung von Issues
Als Community-Mitglieder die Kompromittierung in GitHub issue #24512 meldeten, veröffentlichten die Angreifer innerhalb von 102 Sekunden (12:44–12:46 UTC) 88 Bot-Kommentare über 73 verschiedene Konten. Bei den verwendeten Konten handelte es sich um zuvor kompromittierte Entwicklerkonten, nicht um eigens dafür angelegte Profile. Die Analyse von Rami McCarthy ergab eine Überschneidung von 76 % mit den Konten des Botnetzes, das bei der Offenlegung von Trivy eingesetzt wurde.
Über das kompromittierte Maintainer-Konto krrishdholakia schlossen die Angreifer Issue #24512 mit dem Status „not planned“ und nahmen Commits in nicht zusammenhängenden Repositories mit der Nachricht „teampcp update“ vor.
Die Community eröffnete ein paralleles Tracking-Issue (#24518) und setzte die Diskussion auf Hacker News fort, wo der Thread 324 Punkte erreichte.
Bestätigte Auswirkungen
Die betroffenen Versionen waren etwa 3 Stunden lang auf PyPI verfügbar. Die folgenden Projekte reichten am 24. März Sicherheits-PRs ein oder erstellten Issues, um nicht mehr Version 1.82.7 und 1.82.8 zu verwenden:
Projekt | Beleg |
|---|---|
DSPy | PR #9498 zusammengeführt; CI-Fehlerbericht |
MLflow | PR #21971 zusammengeführt |
OpenHands | |
CrewAI | |
langwatch | |
strands-agents/sdk-python | |
Arize Phoenix | |
nanobot | |
dreadnode/rigging | |
CoPaw | |
Aider | Als sicher bestätigt (verwendet |
Der Mechanismus über .pth wird beim Start jedes Python-Prozesses ausgelöst, auch bei pip selbst. In CI/CD-Umgebungen bedeutet das, dass die Payload während der Build-Schritte ausgeführt werden kann, nicht nur zur Laufzeit der Anwendung.
Erkennung: Sind Sie betroffen?
Schritt 1: Installierte Version überprüfen
Wenn die Ausgabe 1.82.7 oder 1.82.8 anzeigt, behandeln Sie das System als kompromittiert und befolgen Sie die unten beschriebenen Maßnahmen. Führen Sie nicht einfach ein Upgrade durch – die Payload könnte bereits ausgeführt worden sein.
Schritt 2: Nach Persistenz-Artefakten suchen
Schritt 3: Nach schädlichen .pth-Dateien suchen
Schritt 4: Datei-Hashes überprüfen
Schritt 5: Netzwerkindikatoren überprüfen
Schritt 6: Kubernetes überprüfen
Schritt 7: Mit Snyk scannen

Die Banner-Warnung in der Snyk-App zeigt betroffene Repositories im Asset-Inventar an. Über den Link zum Trust Center gelangen Sie zum Echtzeitstatus des Vorfalls.
Snyk-Kunden können auch den litellm-Paketratgeber und den vollständigen Schwachstelleneintrag unter SNYK-PYTHON-LITELLM-15762713 aufrufen.
Maßnahmen zur Behebung
Wenn Sie Version 1.82.7 oder 1.82.8 NICHT installiert haben:
Verwenden Sie <=1.82.6, bis eine unveränderte Version verfügbar ist:
Wenn Sie Version 1.82.7 oder 1.82.8 installiert HABEN:
Die Payload wird beim Start von Python ausgeführt, auch während pip install. Gehen Sie davon aus, dass das System potenziell kompromittiert ist – unabhängig davon, ob Anwendungscode ausgeführt wurde.
Entfernen Sie Persistenz-Artefakte:
Erneuern Sie die Zugangsdaten auf dem betroffenen System:
Private SSH-Schlüssel: Erstellen Sie neue Schlüssel und widerrufen Sie die alten Schlüssel in
authorized_keys, GitHub und GitLabCloud-Zugangsdaten: AWS-Zugriffsschlüssel, GCP-Dienstkontoschlüssel, Azure-Dienstprinzipale
API-Schlüssel:
.env-Dateien, Shell-Umgebungsvariablen, CI/CD-GeheimnisseZugangsdaten für Docker-Registries:
~/.docker/config.jsonKubernetes:
~/.kube/config, Dienstkonto-Tokens innerhalb des ClustersDatenbankpasswörter aus allen Konfigurationsdateien auf dem System
Git-Zugangsdaten aus
~/.gitconfigoder dem System-AnmeldedatenspeicherSeed-Phrasen für Kryptowährungs-Wallets
Überprüfen Sie AWS Secrets Manager und SSM Parameter Store, da die Payload diese direkt abfragt, wenn auf die Instance-Metadaten zugegriffen werden kann.
Überprüfen Sie die Kubernetes-Cluster-Secrets. Wenn ein Dienstkonto-Token vorhanden war, könnten alle Secrets in sämtlichen Namespaces ausgelesen worden sein. Suchen Sie in
kube-systemnach Pods mit dem Namennode-setup-*.
Installieren Sie eine unveränderte Version in einer neuen Umgebung, statt ein In-Place-Upgrade durchzuführen:
Warum die Hash-Prüfung von pip dies nicht erkannt hat
Die Hash-Prüfung bestätigt, dass eine Datei mit der von PyPI angegebenen Datei übereinstimmt. Sie sagt jedoch nicht aus, ob der angegebene Inhalt schädlich ist.
Die Datei litellm_init.pth in Version 1.82.8 ist in der Datei RECORD des Wheels korrekt mit einem passenden Hash aufgeführt. pip install --require-hashes wäre erfolgreich gewesen. Das Paket besteht alle üblichen Integritätsprüfungen, weil der schädliche Inhalt mit legitimen Zugangsdaten veröffentlicht wurde. Es gibt weder eine Hash-Abweichung noch verdächtige Domains oder einen falsch geschriebenen Paketnamen.
Die einzige Möglichkeit, dies während der Installation zu erkennen, besteht darin, zu prüfen, ob ein Paket .pth-Dateien installiert und ob diese Dateien Muster wie subprocess, base64 oder exec enthalten. Derzeit führt kein weit verbreitetes pip-Plugin diese Prüfung automatisch durch.
Das größere Muster
Bei der Auswahl der Ziele in dieser Kampagne liegt der Fokus auf Tools mit weitreichendem Zugriff auf automatisierte Pipelines: einem Container-Scanner (Trivy), einem Infrastructure-Scanning-Tool (KICS) und einer KI-Modell-Routing-Bibliothek (LiteLLM). Jedes dieser Tools benötigt konstruktionsbedingt umfassenden Lesezugriff auf die von ihm genutzten Systeme (Zugangsdaten, Konfigurationen, Umgebungsvariablen).
LiteLLM wird zunehmend als zentralisiertes LLM-Gateway eingesetzt, das API-Zugangsdaten für mehrere Modellanbieter speichert. In dieser Konfiguration ist der Satz an Zugangsdaten, auf den ein einzelner kompromittierter Host Zugriff bietet, umfangreicher als bei einer typischen Anwendung.
Die erste Offenlegung verbreitete sich über KI-Entwickler-Communities (r/LocalLLaMA, r/Python, Hacker News) und nicht über traditionelle Sicherheitskanäle wie r/netsec oder CVE-Feeds.
Weitere Informationen zu Supply-Chain-Risiken speziell bei LLM-Tools finden Sie in Supply Chain Vulnerabilities in LLMs auf Snyk Learn. Auch der Supply-Chain-Angriff über eine AI Pwn Request bei Ultralytics aus dem Jahr 2024 bietet einen nützlichen Vergleich: Eine weitere weit verbreitete KI-Python-Bibliothek wurde über einen CI/CD-Exploit kompromittiert, wobei die Angriffskette ähnlich war.
Kompromittierungsindikatoren
Datei-Hashes:
Datei | SHA-256 |
|---|---|
|
|
|
|
|
|
Netzwerk:
Datenexfiltration:
https://models.litellm.cloud/(POST)C2-Abfrage:
https://checkmarx.zone/raw(GET)
Dateisystem:
~/.config/sysmon/sysmon.pyoder/root/.config/sysmon/sysmon.py~/.config/systemd/user/sysmon.service(Beschreibung: „System Telemetry Service“)/tmp/tpcp.tar.gz,/tmp/session.key,/tmp/payload.enc,/tmp/session.key.enc/tmp/.pg_state,/tmp/pglog
Kubernetes:
Pods:
node-setup-{node_name}inkube-systemContainername:
setup, Image:alpine:latest
RSA-Public-Key-Präfix (in den Payloads aller drei Vorgänge fest codiert):
Was Sie jetzt tun sollten
Überprüfen Sie Ihre litellm-Version:
pip show litellm | grep VersionVerwenden Sie in allen Umgebungen
<=1.82.6Führen Sie
snyk test --package-manager=pipausWenn Version 1.82.7 oder 1.82.8 installiert war: Erneuern Sie die Zugangsdaten und suchen Sie nach Persistenz-Artefakten
Überprüfen Sie CI/CD-Pipelines auf nicht festgelegte Tool-Versionen, einschließlich GitHub Actions
Überprüfen Sie Kubernetes:
kubectl get pods -A | grep node-setup-
WHITEPAPER
Die KI-Sicherheitskrise in Ihrer Python-Umgebung
Angesichts des rasanten Entwicklungstempos: Wissen Sie wirklich, worauf Ihre KI-Umgebung zugreifen kann?
