A Maintainer Account Gets Hijacked
On March 24, 2026 at 10:39 UTC, litellm==1.82.7 was uploaded to PyPI. Thirteen minutes later, 1.82.8 followed. Neither version had a corresponding Git tag or GitHub release. Both were uploaded directly by the threat actor after compromising the PyPI account of krrishdholakia, the litellm maintainer — bypassing the project's entire CI/CD pipeline.
The attack was only discovered by accident. A developer at FutureSearch installed an MCP plugin in Cursor IDE. That plugin pulled in litellm as a transitive dependency. Within seconds, the machine ran out of RAM and crashed — caused by an exponential fork bomb, a bug in the malware itself. Without that bug, the attack would have been completely silent.
A commit pushed to a forked repository by the attacker reads: "teampcp owns BerriAI". The same group was responsible for the Trivy scanner attack (March 19) and the KICS compromise. The exfiltrated archive filename — tpcp.tar.gz — is a direct reference to the group's name.
Anatomy of the Payload
The attack operates differently across the two versions, with 1.82.8 representing an escalated, more aggressive iteration. Here's what version 1.82.8 does from the moment litellm is installed:
The .pth Trick — Why No Import Is Needed
Python's site module processes all .pth files in site-packages/ at interpreter startup. The malicious file litellm_init.pth (34,628 bytes, listed in the package's own RECORD) contains:
import os, subprocess, sys; subprocess.Popen([
sys.executable, "-c",
"import base64; exec(base64.b64decode('...[34KB of double-encoded payload]...'))"
])
This spawns a child Python process carrying the full payload. Because .pth files trigger on every interpreter startup, the child re-triggers the same file — creating an exponential fork bomb. The fork bomb was not intentional. It is a bug. Without it, this attack would still be undetected in countless environments.
Version 1.82.7 was slightly less aggressive — the payload was embedded directly in proxy/proxy_server.py, requiring an explicit import litellm to trigger. Version 1.82.8 removed that requirement entirely.
Sweeps the filesystem for SSH private keys, .env files, AWS/GCP/Azure credentials, Kubernetes configs, database passwords, shell history, Docker configs, npm tokens, crypto wallet files, and CI/CD configs. Also runs printenv to capture all live environment variables — API keys, secrets, tokens, anything in the process environment.
Collected data is encrypted using AES-256-CBC with a random 32-byte session key. The session key is itself encrypted with a hardcoded 4096-bit RSA public key. Both are bundled into tpcp.tar.gz and POSTed to https://models.litellm.cloud/ — a lookalike domain registered specifically for this attack (the legitimate domain is litellm.ai).
If a Kubernetes service account token is present, the payload reads all secrets across all namespaces and attempts to create a privileged alpine:latest pod on every node in kube-system. Each pod mounts the host filesystem and drops a persistent backdoor at ~/.config/sysmon/sysmon.py with a systemd service that polls a C2 server for updated binaries.
LiteLLM is an LLM API gateway — its entire purpose is to manage API keys for OpenAI, Anthropic, Google, and 100+ other providers. Any machine running it is, by definition, a treasure chest of high-value credentials. The attacker knew exactly what they'd find.
What's Safe, What's Not
| Version | Status | Trigger Mechanism | Notes |
|---|---|---|---|
| ≤ 1.82.6 | CLEAN | — | Last known-good release. Pin here. |
| 1.82.7 | COMPROMISED | Requires import litellm | Payload in proxy/proxy_server.py |
| 1.82.8 | CRITICAL | Triggers on Python startup — no import needed | Malicious .pth file. Fork bomb bug caused discovery. |
You may have never run pip install litellm yourself. LiteLLM is a dependency of many AI agent frameworks, MCP servers, and LLM orchestration tools. Check all your Python environments, not just your primary one. CI/CD containers, virtual envs in project directories, and tool-managed environments like Cursor and Claude Code are all in scope.
How to Check if You're Affected
Run these commands on any machine where you use Python-based AI tooling — especially Cursor, Claude Code, or any environment with MCP plugins installed.
pip show litellm
# Look for: Version: 1.82.7 or 1.82.8 → you are affected
find / -name "litellm_init.pth" 2>/dev/null
find ~/.cache/uv -name "litellm_init.pth" 2>/dev/null
find ~/.local -name "litellm_init.pth" 2>/dev/null
ls ~/.config/sysmon/sysmon.py 2>/dev/null
ls ~/.config/systemd/user/sysmon.service 2>/dev/null
kubectl get pods -n kube-system | grep node-setup
kubectl get secrets --all-namespaces | grep -i suspicious
Treat the machine as fully compromised. The window between install and exfiltration is seconds. Assume all of the following were stolen and rotate immediately:
SSH keys · AWS/GCP/Azure credentials · All .env API keys · Kubernetes configs · GitHub tokens · Database passwords · Docker credentials · Shell history (may contain secrets passed as args)
# Remove the package
pip uninstall litellm -y
# Purge package manager caches to prevent re-install from cache
rm -rf ~/.cache/uv
pip cache purge
# Remove persistence if found
rm -rf ~/.config/sysmon/
systemctl --user disable sysmon.service 2>/dev/null
rm ~/.config/systemd/user/sysmon.service 2>/dev/null
The MCP Ecosystem Is an Emerging Attack Surface
This attack didn't just exploit a Python package. It exploited a structural property of how modern AI tooling gets assembled — and it landed on machines running Cursor and Claude Code because of it.
"The person who discovered this attack only found it because their machine crashed. Without that bug, this would still be running silently on thousands of developer machines right now."
MCP (Model Context Protocol) plugins are a young, largely unvetted ecosystem. There is no curated review process. Plugins can pull in arbitrary Python packages. And the machines running these tools — developer workstations, CI runners — are loaded with the exact credentials attackers want.
Claude Code users face compounded risk. Claude Code is an agentic tool with broad file system access and code execution capabilities by design. It also has documented support for LiteLLM proxy as an MCP integration. Beyond the litellm vector, Check Point Research separately disclosed vulnerabilities in Claude Code where malicious repository configuration files could trigger arbitrary shell commands and API key exfiltration simply by opening a project — all issues now patched by Anthropic.
The pattern here is the same across all these attacks: configuration and tooling layers have become part of the execution surface. A .pth file is not code you write. An MCP plugin dependency is not a package you explicitly chose. But both run with full privileges on your machine.
How to Reduce Your Exposure
No single control fully prevents supply chain attacks, but layered defenses significantly shrink the blast radius.
Use lockfiles (uv.lock, poetry.lock, pinned requirements.txt). Never upgrade blindly. litellm==1.82.6 would have been safe here. Treat upgrades as intentional decisions, not automatic steps.
Use pip-audit, uv tree, or pipdeptree to know what you've actually installed and why. If you didn't explicitly install a package, you should know what pulled it in.
The biggest tell here: 1.82.7 and 1.82.8 existed on PyPI with no GitHub tag. Tools like Socket.dev, Endor Labs, or Sigstore can detect packages published outside normal CI/CD pipelines automatically.
AWS OIDC tokens in CI instead of long-lived access keys. Rotate API keys regularly. Use a secrets manager instead of .env files on disk. Static secrets sitting on developer machines are the attacker's jackpot.
Run MCP servers in Docker containers rather than directly in your host Python environment. Docker MCP Toolkit provides isolated execution compatible with Claude Desktop, Cursor, and VS Code, preventing installed packages from touching your host filesystem.
A .pth file in a third-party package has essentially no legitimate use. Add a CI check or SAST rule that flags any .pth file appearing in installed dependencies. This is low noise, high signal.
Immediate Action Checklist
- Run pip show litellm in every Python environment on developer machines and CI runners
- Search for litellm_init.pth in all site-packages directories and package manager caches
- Check for persistence indicators: ~/.config/sysmon/ and sysmon.service
- If found: rotate all credentials accessible from that machine immediately
- Pin all projects to litellm<=1.82.6 until a verified clean release is available
- Audit MCP plugins for their transitive dependency trees before installation
- Enable PyPI Trusted Publishers for any packages your team maintains
Assume that at some point, a dependency in your stack will be compromised. Design your credential hygiene around that assumption: minimal secrets on any given machine, short-lived tokens, isolated execution environments, and regular rotation. The goal isn't to make compromise impossible — it's to make it survivable.
This Campaign Isn't Over
TeamPCP has now crossed five supply chain ecosystems in under a month — GitHub Actions, Docker Hub, npm, OpenVSX, and PyPI. Each compromised environment yields credentials that unlock the next target. The 13-minute gap between litellm 1.82.7 and 1.82.8 shows an attacker actively iterating during the attack window, escalating the trigger mechanism in real time.
The AI developer tooling ecosystem is a particularly attractive target: high-privilege machines, dense credential environments, a young and fast-moving plugin ecosystem with minimal security review, and the implicit trust developers place in tools they use every day. That combination will continue to be exploited.
The best defense is treating every layer of your tooling stack — not just your own code — as part of your attack surface.
FutureSearch: futuresearch.ai/blog/litellm-pypi-supply-chain-attack
GitHub Issue #24512: github.com/BerriAI/litellm/issues/24512
Endor Labs Analysis: endorlabs.com/learn/teampcp-isnt-done
Check Point Research (Claude Code): blog.checkpoint.com/research/check-point-researchers-expose-critical-claude-code-flaws