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.

Shi's AI Notebook
Shi's AI Notebook
Shi's AI Notebook
LiteLLM Compromised in 46 Minutes: Inside the 47,000‑Download Supply‑Chain Attack

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonKubernetesSecurityPyPISupply Chain AttackLiteLLMTeamPCP
Shi's AI Notebook
Written by

Shi's AI Notebook

AI technology observer documenting AI evolution and industry news, sharing development practices.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.