LiteLLM is a highly popular open-source Python library and proxy server that provides a unified interface for calling over 100+ Large Language Model (LLM) APIs, such as OpenAI, Anthropic, Bedrock, and VertexAI, using the standard OpenAI input/output format. It simplifies multi-LLM integration, offering features like automatic fallbacks, retries, and cost tracking. Because it functions as an API gateway, it acts as a credential aggregator by design, securely holding API keys for various LLM providers.
Overview
LiteLLM is widely deployed by organisations such as Stripe, Netflix, and Google ADK. Furthermore, it handles over 95 million monthly downloads and is heavily relied upon as a transitive dependency in major AI agent frameworks, including CrewAI, DSPy, Opik, Browser-Use, MLflow, and OpenHands.
A financially motivated threat actor group known as TeamPCP (also tracked as DeadCatx3, PCPcat, ShellForce, and CipherForce) executed a critical software supply chain attack on the official `litellm` package on the Python Package Index (PyPI). TeamPCP, who reportedly collaborates with the LAPSUS$ extortion group, targeted the PyPI publishing credentials of LiteLLM’s CEO and core maintainer, Krrish Dholakia.
Who and what was affected?
The attackers published two malicious, backdoored versions (1.82.7 and 1.82.8) directly to PyPI, completely bypassing the official GitHub CI/CD release process:
- Version 1.82.7 included an injected base64-encoded payload in `litellm/proxy/proxy_server.py` that executed maliciously whenever the module was imported.
- Version 1.82.8 included a highly dangerous `litellm_init.pth` file placed at the wheel root. Python's native path configuration features process `.pth` files automatically upon interpreter startup. This meant the malware ran in the background every single time a Python process started, regardless of whether the user explicitly imported LiteLLM.
Any organisation, developer, CI/CD pipeline, or Docker build process that ran `pip install litellm` (or pulled it as an unpinned transitive dependency) on March 24, 2026, between 10:39 UTC and approximately 16:00 UTC, is affected.
Who is NOT affected: Users of the official LiteLLM Proxy Docker image (`ghcr.io/berriai/litellm`) and LiteLLM Cloud were not compromised, as their dependencies were strictly pinned to safe versions.
The malware unleashed a devastating three-stage attack:
- Systematic Credential Harvesting: It swept affected systems and collected LLM API keys, SSH keys, AWS/GCP/Azure cloud credentials, Kubernetes service account tokens, Docker registry auth tokens, database connection strings, Git credentials, shell histories, CI/CD secrets, and cryptocurrency wallets.
- Exfiltration: The stolen data was bundled into an archive (`tpcp.tar.gz`), encrypted using a hybrid AES-256 and RSA-4096 scheme, and silently sent to the attacker-controlled `models.litellm[.]cloud`.
- Lateral Movement & Persistence: On Kubernetes clusters, it used accessible service account tokens to read all cluster secrets and deploy a highly privileged `alpine:latest` pod (`node-setup-*`) to every node. It then installed a persistent systemd backdoor (`sysmon.py` and `sysmon.service`) that periodically polled `checkmarx[.]zone/raw` to download and execute arbitrary second-stage payloads from the attackers.
Timeline of Events
- Late February 2026: An autonomous AI bot named "hackerbot-claw" exploited a misconfigured pull request workflow in Aqua Security's Trivy repository, stealing a privileged GitHub token.
- March 19, 2026: TeamPCP used residual access from the Trivy breach to distribute a credential-stealing Trivy binary and poisoned GitHub actions. Because LiteLLM utilized Trivy in its own CI/CD security scanning workflow without pinning the version, the compromised Trivy scanner silently harvested LiteLLM's `PYPI_PUBLISH` token.
- March 20–23, 2026: The threat actors deployed a self-propagating worm ("CanisterWorm") across the npm ecosystem and compromised Checkmarx KICS GitHub actions. They also registered a malicious exfiltration domain, `models.litellm[.]cloud`, to mimic legitimate LiteLLM infrastructure and a C2 domain `checkmarx[.]zone`.
- March 24, 2026, 10:39 UTC: TeamPCP used the stolen PyPI token to publish the malicious `litellm` version 1.82.7 to PyPI.
- March 24, 2026, 10:52 UTC: The attackers escalated the attack by publishing version 1.82.8, which added the aggressive `.pth` file execution vector.
- March 24, 2026, 11:48 UTC: Security researchers at FutureSearch discovered the compromise after the malware's `.pth` delivery mechanism accidentally created an exponential "fork bomb" that crashed their system.
- March 24, 2026, 12:44 UTC: The attackers deployed a botnet to spam the GitHub disclosure issue and used compromised maintainer accounts to temporarily deface repositories and close the issue as "not planned" to disrupt the incident response.
- March 24, 2026, 13:38 UTC: The PyPI security team successfully quarantined the entire `litellm` project, blocking further downloads.
- March 24, 2026, 15:27 UTC: The malicious versions were permanently deleted, maintainer accounts were recovered, and all keys were successfully rotated.
Recommended Mitigation Steps
If you suspect your system, CI/CD pipeline, or Docker image encountered `litellm` 1.82.7 or 1.82.8, you must take the following remediation actions immediately:
- Identify Exposure: Check all Python environments to see if versions 1.82.7 or 1.82.8 are currently installed (`pip show litellm | grep Version`), and explicitly search for the presence of the `litellm_init.pth` file in `site-packages`.
- Assume Full Compromise & Rotate Secrets: If either version was present, you must assume all credentials, cloud tokens, database passwords, LLM keys, and SSH keys accessible to the environment have been stolen. Rotate every credential immediately.
- Eliminate Persistence: Stop and disable the `sysmon.service` systemd unit, and delete `~/.config/sysmon/sysmon.py`, `/tmp/pglog`, and `/tmp/.pg_state`. In Kubernetes environments, thoroughly audit the `kube-system` namespace and delete any attacker pods matching `node-setup-*`.
- Purge and Rebuild Environments: Do not simply downgrade the package. Delete and recreate Python virtual environments entirely. Purge local package manager caches (`pip cache purge` or `rm -rf ~/.cache/uv`) to prevent the accidental reinstallation of cached malicious wheels. Rebuild affected CI environments from clean base images.
- Pin Dependencies: Ensure that your environments are pinned to the last known-clean version (`litellm==1.82.6` or earlier).
- Block Malicious Infrastructure: Block outbound network connections and DNS resolution for the known IOCs at your network perimeter.
Indicators of Compromise (IOCs)
|
Category |
Indicator |
Description |
|
File Hash |
8395c3268d5c5dbae1c7c6d4bb3c318c752ba4608cfcd90eb97ffb94a910eac2 |
1.82.7 wheel (SHA-256) |
|
File Hash |
d2a0d5f564628773b6af7b9c11f6b86531a875bd2d186d7081ab62748a800ebb |
1.82.8 wheel (SHA-256) |
|
File Hash |
71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238 |
litellm_init.pth (SHA-256) |
|
File Hash |
a0d229be8efcb2f9135e2ad55ba275b76ddcfeb55fa4370e0a522a5bdee0120b |
Malicious proxy_server.py (SHA-256) |
|
Network |
models.litellm[.]cloud |
Primary exfiltration endpoint |
|
Network |
checkmarx[.]zone |
Persistence C2 endpoint |
|
Network |
checkmarx[.]zone/raw |
Payload delivery polling endpoint |
|
Filesystem |
.../site-packages/litellm_init.pth |
Interpreter startup payload |
|
Filesystem |
~/.config/sysmon/sysmon.py |
Persistent backdoor script (also in /root/) |
|
Filesystem |
~/.config/systemd/user/sysmon.service |
Malicious unit ("System Telemetry Service") |
|
Filesystem |
/tmp/pglog |
Downloaded binary payload |
|
Filesystem |
/tmp/.pg_state |
Malware state tracking file |
|
Filesystem |
tpcp.tar.gz |
Exfiltration archive |
|
Kubernetes |
Pods: node-setup-* |
Located in kube-system namespace |
|
Kubernetes |
Container Image: alpine:latest |
Used within the setup container |
If you are worried about any of the threats outlined in this bulletin or need help in determining what steps you should take to protect yourself from the most material threats facing your organisation, please contact your account manager, or alternatively get in touch to find out how you can protect your organisation.
