LiteLLM Compromised in 46 Minutes: Inside the 47,000‑Download Supply‑Chain Attack
In March 2026, attackers hijacked the official PyPI maintainer account of LiteLLM, released two malicious versions that were downloaded 46,996 times in 46 minutes, exfiltrated credentials, launched a fork‑bomb, and demonstrated how unpinned dependencies and .pth files can turn a simple package install into a full‑scale supply‑chain breach.
Incident Overview
On March 24, 2026 the PyPI account of LiteLLM’s maintainer was compromised. Within roughly 46 minutes two malicious releases (versions 1.82.7 and 1.82.8) were published and downloaded 46,996 times before PyPI isolated the packages. Snyk assigned a CVSS score of 9.3 (Critical).
Malicious Payloads
Version 1.82.7 injected code in proxy_server.py that activates when the litellm.proxy module is imported. The payload contacts checkmarx.zone/raw to exfiltrate SSH keys, .env files, cloud credentials, Kubernetes configs, database passwords, .gitconfig, shell history, encrypted wallets, and cloud metadata.
Version 1.82.8 leveraged a .pth file, a standard Python site‑packages feature that executes automatically on interpreter start‑up. The .pth payload contacts models.litellm.cloud and runs without any explicit import.
Payload Encryption
The payload is double‑base64‑encoded, then encrypted with a random 32‑byte AES‑256‑CBC session key generated via openssl. The session key is encrypted with a hard‑coded 4096‑bit RSA public key, packaged into tpcp.tar.gz, and exfiltrated via a curl POST request, making network interception ineffective.
46‑Minute Timeline
Mar 23 – attacker registers litellm.cloud domain.
Mar 24 08:30 UTC – compromised maintainer account ( krrishdholakia) publishes malicious versions.
10:39 – version 1.82.7 released with proxy_server.py payload.
10:52 – version 1.82.8 released with .pth payload.
10:58 – Cursor’s MCP plugin reconnects, uvx auto‑downloads LiteLLM and 77 transitive dependencies (≈14.9 MiB).
~10:59‑11:08 – fork‑bomb creates ~11,000 Python processes, exhausting RAM.
11:08 – system becomes unresponsive; forced shutdown.
11:25 – PyPI security team isolates the malicious packages.
Discovery
FutureSearch engineer Callum McMahon noticed the crash caused by the malicious code itself. The .pth file decodes the payload, launches a subprocess via subprocess.Popen, which triggers another .pth execution, creating an exponential fork‑bomb.
Using Claude Code, McMahon reverse‑engineered the payload within two minutes and published a detailed technical blog within four minutes, all within a single AI conversation.
Impact Assessment
46,996 downloads in 46 minutes.
2,337 PyPI packages list LiteLLM as a direct dependency.
2,054 packages (88 %) allow the malicious version via unconstrained version ranges; only 283 packages (12 %) are protected by pinned versions or upper bounds.
Infection paths: direct install (pip/uv), transitive dependency, and CI/CD pipeline rebuilds during the window.
Users who only import the SDK without litellm.proxy may see no symptoms, making detection difficult.
Attacker Attribution
Snyk attributes the campaign to TeamPCP (also known as PCPcat, ShellForce, DeadCatx3), a group that emerged in late 2025 targeting cloud‑native infrastructure. Earlier they compromised Trivy, stealing CI secrets, and simultaneously deployed the ZOMBI remote‑access trojan via malicious VSCode/Cursor extensions and large‑scale GitHub account hijacks.
Lateral Movement and Persistence
Local persistence: writes ~/.config/sysmon/sysmon.py and creates a systemd user service.
Kubernetes lateral spread: enumerates all namespaces, reads secrets, and deploys privileged alpine:latest pods that mount the host filesystem and install backdoors.
.pth Files – An Overlooked Attack Surface
The .pth mechanism executes before any user code, meaning that a malicious .pth runs during pip install or any CI/CD environment creation, bypassing network isolation.
GitHub Source Integrity
The LiteLLM source repository on GitHub was never compromised; the malicious code existed only in the wheel files uploaded directly to PyPI. The highest release tag is v1.82.6.dev1. Versions 1.82.7 and 1.82.8 were uploaded using stolen PyPI credentials, bypassing GitHub CI/CD.
Mitigation Steps
Check installed version: pip show litellm; remove 1.82.7/1.82.8 immediately.
Clear caches: rm -rf ~/.cache/uv or pip cache purge.
Search for persistence artifacts: ~/.config/sysmon/sysmon.py, ~/.config/systemd/user/sysmon.service, and suspicious pods prefixed with node-setup- in the kube-system namespace.
Rotate all exposed credentials: SSH keys, cloud provider keys, Kubernetes configs, .env API keys, and database passwords.
Audit Trivy versions ( aquasecurity/trivy-action, aquasecurity/setup-trivy) for possible contamination.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Shi's AI Notebook
AI technology observer documenting AI evolution and industry news, sharing development practices.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
