TeamPCP poisons the LiteLLM AI gateway on PyPI to harvest LLM API keys
Real-world incident24 Mar 2026🗺️ Model / Package Supply ChainAs part of a multi-ecosystem supply-chain cascade (Trivy onward), TeamPCP used stolen PyPI publishing tokens to ship backdoored BerriAI LiteLLM versions whose auto-running .pth payload harvested cloud, SSH and Kubernetes secrets plus env vars holding OPENAI_API_KEY/ANTHROPIC_API_KEY — exfiltrating to a typosquatted C2; AI-talent firm Mercor was a downstream victim, with Lapsus$ claiming ~4TB stolen.
Root cause — why it happened
Lots of AI apps don't talk to each LLM provider directly — they route everything through a shared 'gateway' library that holds all the provider keys in one place. The popular open-source gateway here is LiteLLM, installed from the public Python package index (PyPI). Attackers stole the credentials that let someone publish new versions of LiteLLM, then quietly shipped two booby-trapped releases. One of them dropped a special file (a `.pth` file) that Python runs automatically the moment any Python program starts — so you didn't even have to use LiteLLM for the trap to spring. Once it ran, it grabbed every secret it could find on the machine — cloud passwords, server keys, and all the LLM API keys sitting in environment variables — encrypted them, and shipped them off to a lookalike attacker website. Because the gateway layer is exactly where all the keys live together, one poisoned package handed the attacker the whole key ring at once.
Risks this case illustrates
Named in the standard (OWASP/ATLAS/NIST) lens. Click a highlighted component in the diagram below to see which risks attach where.
How it unfolded
Stolen publishing tokens reach PyPI
The attackers didn't break into LiteLLM's code so much as steal the keys that let someone publish new versions of it. Per the researchers, those publishing tokens were picked up in an earlier break-in of a different security tool (Trivy), then reused here. With the keys in hand, the attacker can upload a new 'LiteLLM' that the whole world will trust, because it comes from the real package's name.
pypi: berriai/litellm publisher token: STOLEN (reportedly via earlier Trivy compromise) 1.82.7 -> malicious code injected into proxy_server module 1.82.8 -> ships litellm_init.pth inside the wheel package name/owner: UNCHANGED (consumers see nothing odd) C2 domain registered ~1 day before the attack
Controls & guardrails — what would have stopped it
Three things would have blunted this. First, don't trust a package by name alone — lock each dependency to an exact, reviewed version and check its fingerprint, so a backdoored release the attacker pushes with stolen keys doesn't match and won't install. Second, don't keep all your keys in one easy-to-grab pile next to the gateway — hand them out only when needed and for a short time, so a snoop on the machine finds little. Third, control where the machine can phone home: if it can only reach approved addresses, the secret-stuffed message to the lookalike attacker site gets blocked. The honest catch: pinning only helps if you review before you bump the version, and a determined attacker can still route data through somewhere you already allow.
- Weight provenance, hashing & pre-deploy evals
Hashes prove the file is unchanged, not that it's safe — a trained-in backdoor or ablated refusal direction passes integrity checks. Only behavioural evals probe disposition, and they can't be exhaustive.
- Serving-stack & provisioning attestation, cache isolation
Attestation is operationally heavy and rarely covers the full stack; cache isolation trades away latency/cost savings, so it's often left on for performance. Signing proves a template wasn't tampered in transit, not that a signed template is benign — an insider with signing rights still needs review and trigger-focused evals.
- Least-privilege identity & scoped credentials
Doesn't prevent manipulation — only caps its reach. Hard to get right operationally; over-broad scopes are the common real-world failure.
- Egress allowlisting & DLP on tool arguments
Allowlists fight an open-ended channel; legitimate-but-broad destinations (any URL fetch, any email) are hard to constrain without breaking usefulness. Encoding can evade naive DLP.
- Runtime monitoring & anomaly detectionaddressesSensitive Data Leakage
Detects the anomalous, not the novel-but-subtle; high false-positive rates cause alert fatigue. Always a step behind a sufficiently quiet attacker.
- Full-trace audit logging
Logging is forensic, not preventive — it explains harm after the fact. Useless if no one reviews it or if the materialised context isn't captured.
- Governance: risk assessment, red-teaming & incident response
Process reduces likelihood and speeds recovery but executes no technical control itself; weak follow-through makes it theatre.
- Loop/cost circuit-breakers & consistency checks
Thresholds are blunt — too tight breaks legitimate long tasks, too loose lets damage accrue first. Catches runaway dynamics, not a single well-formed bad decision.
Lessons
- ▸ The AI-gateway/proxy layer is uniquely high-value collateral: it concentrates multi-provider LLM keys alongside cloud and cluster credentials, so one compromised dependency there harvests the whole secret estate at once.
- ▸ Trust the artifact, not the name: a stolen publishing token lets an attacker ship a backdoor under a trusted package name — pin to reviewed versions and verify hashes/signatures on every install rather than resolving by name/tag.
- ▸ Installing a package can run code at startup, not just on import: a `.pth` file executes on essentially any Python process on the host, a far broader trigger than `import litellm` — scan dependencies for unexpected `.pth`/post-install hooks.
- ▸ Treat LLM API keys as crown-jewel secrets: keep them out of long-lived plaintext environment variables, issue short-lived scoped tokens from a broker, and monitor for anomalous spend/egress that signals key theft.
- ▸ Behavioural evals can't catch this — there is no model behaviour to test; the compromise lives in the install and runtime, so the controls are supply-chain hygiene, secrets isolation, and deny-by-default egress.
- ▸ Supply-chain attacks cascade across ecosystems: tokens stolen from one tool (reportedly Trivy) were reused to poison another (LiteLLM) — assume a single credential theft can pivot into your dependencies.
Proposals & gaps this case surfaced
Non-destructive suggestions for the library — proposed, not adopted.
A shared LLM gateway/proxy or aggregation layer concentrates many providers' API keys — often alongside cloud and cluster credentials — in one process/host environment, so a single compromise of that layer (a poisoned dependency, an exposed endpoint, or a leaked image) exposes the organisation's entire AI key estate and adjacent secrets at once.
Do not store long-lived multi-provider LLM keys (or ambient cloud/K8s credentials) in the gateway/proxy's plaintext process environment. Issue short-lived, scoped tokens from a secret broker at request time, isolate the serving stack from host cloud/cluster credentials, and monitor per-provider spend and egress so a stolen key surfaces as anomalous usage — capping the loot a compromised gateway dependency can harvest.
This case shows a gap: we treat 'don't run poisoned packages' as the lesson, but the reason it hurt so much is that ALL the AI keys lived in one easy-to-grab place. Keeping keys spread out and short-lived deserves to be its own safeguard, not an afterthought.
These surface as proposals across the Control Library and Risk Taxonomy; adopt them by hand when ready.
Sources
- Weaponizing the Protectors: TeamPCP's Multi-Stage Supply Chain Attack on Security Infrastructure — Unit 42, Palo Alto Networks (primary) ↗
- LiteLLM and Telnyx compromised on PyPI: Tracing the TeamPCP supply chain campaign — Datadog Security Labs ↗
- Your AI Gateway Was a Backdoor: Inside the LiteLLM Supply Chain Compromise — Trend Micro ↗
- AI Firm Mercor Confirms Breach as Hackers Claim 4TB of Stolen Data — Hackread ↗
- Weaponizing the Protectors: TeamPCP's Multi-Stage Supply Chain Attack on Security Infrastructure — Unit 42, Palo Alto Networks (primary) ↗ — Primary research: stolen PyPI tokens (reportedly via Trivy), 1.82.7 vs 1.82.8, litellm_init.pth startup execution, 50+ secret categories incl. LLM keys, RSA-4096+AES-256 exfil to models[.]litellm[.]cloud.
- LiteLLM and Telnyx compromised on PyPI: Tracing the TeamPCP supply chain campaign — Datadog Security Labs ↗ — Three-stage payload (harvester, K8s lateral movement via node-setup-* pods, sysmon.py/systemd persistence); why .pth executes on startup vs import.
- Your AI Gateway Was a Backdoor: Inside the LiteLLM Supply Chain Compromise — Trend Micro ↗ — Frames the AI-gateway/proxy layer as uniquely high-value collateral concentrating multi-provider keys; the 'over 50 categories' harvester framing follows this reporting.
- 33K Exposed LiteLLM Deployments and the C2 Servers Behind TeamPCP's Supply Chain Attack — Hunt.io ↗ — Source for the C2 detail: models[.]litellm[.]cloud registered 23 Mar 2026 — ~1 day before the 24 Mar attack — typosquatted to blend into LiteLLM traffic.
- TeamPCP (UNC6780): AI Supply Chain's Most Active Threat Actor — CSA Lab Space research note ↗ — Source for the UNC6780 attribution: Google GTIG tracks TeamPCP as UNC6780 (also reported via ISC SANS).
- AI Firm Mercor Confirms Breach as Hackers Claim 4TB of Stolen Data — Hackread ↗ — Downstream impact: Mercor confirmed affected; Lapsus$ claimed ~4TB (claim, not independently confirmed).
Practise the risk class — related scenarios
A support email hides instructions — and the assistant obeys them
A text-to-SQL agent runs the model's output straight at the database
A speed optimisation becomes a cross-tenant listening device
Compromise the pipeline that builds agents, and every new worker is born malicious
Two doors to the same secret: reconstruct the model through its API, or just walk off with the weight file
A fake Sentry error report hijacks a developer's coding agent into running a shell command
The safety guard is itself a trained model — and someone poisoned its lessons
The forensic record is itself the attack surface — an agent's log is poisoned, then quietly rewritten
A cost-saving open-weights swap quietly ships a model with its safety surgically removed
A screenshot that's harmless at full size becomes an order once the system shrinks it
A capable third-party model that behaves perfectly — until it sees the trigger
An attacker captures the agent's bearer token — and inherits its authority
A trusted MCP email tool quietly BCCs every message to an attacker
A forged peer registers on the agent directory — and the planner enlists it
An inbox summary quietly ships a secret to an attacker's server