How a hijacked maintainer account and a malicious .pth file turned the booming MCP plugin ecosystem into one of the most targeted credential-theft operations against AI developers yet.
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, and 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 that was a bug in the malware itself. Without that bug, the attack would have been completely silent.
proxy/proxy_server.py.litellm_init.pth so no import is needed.<=1.82.6.A commit pushed to a forked repository by the attacker reads "teampcp owns BerriAI". The same group was behind the Trivy scanner attack on March 19 and the KICS compromise, and the exfiltrated archive filename, tpcp.tar.gz, is a direct reference to the group's name.
The attack behaves differently across the two versions, with 1.82.8 being the escalated, more aggressive iteration. Here is what 1.82.8 does from the moment litellm is installed.
Python's site module processes every .pth file in site-packages/ at interpreter startup. The malicious file litellm_init.pth (34,628 bytes, listed in the package's own RECORD) contains a one-line trigger.
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. That fork bomb was not intentional. It is a bug, and without it this attack would still be undetected in countless environments.
Version 1.82.7 was slightly less aggressive. Its payload was embedded directly in proxy/proxy_server.py and needed an explicit import litellm to fire. Version 1.82.8 removed that requirement entirely.
.env files, cloud credentials across AWS, GCP and Azure, Kubernetes configs, database passwords, shell history, Docker configs, npm tokens and crypto wallet files. It then runs printenv to capture every live environment variable, so any API key or secret in the process environment goes too.
tpcp.tar.gz and POSTed to https://models.litellm.cloud/, a lookalike domain registered specifically for this attack. The legitimate domain is litellm.ai.
alpine:latest pod on every node in kube-system. Each pod mounts the host filesystem and drops a 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 job is to manage API keys for OpenAI, Anthropic, Google and 100-plus other providers, so any machine running it is by definition a treasure chest of high-value credentials. The attacker knew exactly what they would find.
| Version | Status | Trigger | 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 | Fires on Python startup, no import needed | Malicious .pth file. The fork-bomb bug is what caused discovery. |
You may have never run pip install litellm yourself. LiteLLM is a dependency of many AI agent frameworks, MCP servers and orchestration tools, so check all your Python environments, not just the primary one. CI/CD containers, project-local virtual envs, and tool-managed environments like Cursor and Claude Code are all in scope.
Run these on any machine where you use Python-based AI tooling, especially Cursor, Claude Code, or anything with MCP plugins installed.
pip show litellm
# Version: 1.82.7 or 1.82.8 means 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, so assume everything reachable from that machine was stolen and rotate it immediately.
SSH keys, AWS/GCP/Azure credentials, every .env API key, Kubernetes configs, GitHub tokens, database passwords, Docker credentials, and shell history (which often contains secrets passed as arguments).
# Remove the package pip uninstall litellm -y # Purge caches so it can't reinstall 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
This attack did not 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 only found it because their machine crashed. Without that bug, it would still be running silently on thousands of developer machines right now."
MCP 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 and CI runners) are loaded with the exact credentials attackers want.
Claude Code users face compounded risk. It is an agentic tool with broad filesystem access and code execution by design, and it has documented support for the LiteLLM proxy as an MCP integration. Beyond the litellm vector, Check Point Research separately disclosed vulnerabilities in Claude Code where a malicious repository configuration file could trigger arbitrary shell commands and API-key exfiltration simply by opening a project. Those issues are now patched by Anthropic.
The pattern is the same across all of these attacks: the configuration and tooling layers have become part of the execution surface. A .pth file is not code you wrote. An MCP plugin dependency is not a package you explicitly chose. Both run with full privileges on your machine.
No single control fully prevents supply-chain attacks, but layered defenses shrink the blast radius considerably.
Use lockfiles (uv.lock, poetry.lock, a pinned requirements.txt) and never upgrade blindly. litellm==1.82.6 would have been safe. Treat upgrades as decisions, not automatic steps.
Use pip-audit, uv tree, or pipdeptree to know what you actually installed and why. If you did not 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 detect packages published outside the normal CI/CD pipeline.
Prefer AWS OIDC tokens in CI over long-lived access keys, rotate API keys, and use a secrets manager instead of .env files on disk. Static secrets on developer machines are the jackpot.
Run MCP servers in Docker containers rather than your host Python environment. The Docker MCP Toolkit gives isolated execution compatible with Claude Desktop, Cursor and VS Code, keeping installed packages off your host filesystem.
A .pth file in a third-party package has essentially no legitimate use. A CI or SAST rule that flags any .pth appearing in installed dependencies is low noise and high signal.
pip show litellm in every Python environment on developer machines and CI runners.litellm_init.pth in all site-packages directories and package-manager caches.~/.config/sysmon/ and sysmon.service.litellm<=1.82.6 until a verified clean release ships.Assume that at some point a dependency in your stack will be compromised, and design your credential hygiene around that assumption: minimal secrets on any given machine, short-lived tokens, isolated execution, and regular rotation. The goal is not to make compromise impossible. It is to make it survivable.
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, and a young plugin ecosystem with minimal security review combine with the implicit trust developers place in the tools they use every day. That combination will keep getting exploited.
The best defense is to treat every layer of your tooling stack, not just your own code, as part of your attack surface.
FutureSearch · litellm-pypi-supply-chain-attack
GitHub issue #24512 · BerriAI/litellm
Endor Labs · teampcp-isnt-done
Check Point Research · critical Claude Code flaws