March 28, 2026  ·  8 min read  ·  Supply Chain Security

The Attack That Slipped Past 3.4 Million Developers — And How to Stop It

3 days ago, litellm 1.82.8 hit PyPI. 3 hours later it was gone. But not before infecting unknown numbers of CI/CD pipelines, developer machines, and cloud environments.

Action required: If you installed litellm between March 24–27, 2026, assume compromise and rotate all credentials accessible from that machine — SSH keys, AWS/GCP tokens, crypto wallets, Slack, Discord, .env files.

What Happened

On March 24, 2026, a threat group called TeamPCP published two malicious versions of litellm — one of the most popular AI tooling packages in the Python ecosystem. LiteLLM has 3.4 million daily downloads. It's in the dependency tree of virtually every serious AI agent project.

The attack didn't use a zero-day. It used something far simpler: a .pth file.

What's a .pth file?

When Python starts, it reads every .pth file in your site-packages directory. If the file contains an import statement, Python executes it — silently, before your code runs.

TeamPCP used this to plant a three-stage credential stealer:

Python starts
  → reads site-packages/litellm.pth
  → executes base64-decoded payload
  → exfiltrates: SSH keys, AWS/GCP tokens, crypto wallets,
                 Slack tokens, Discord tokens, .env files

No prompts. No warnings. No logs.

The full campaign

This wasn't one attack. It was a coordinated supply chain operation:

DateTargetImpact
Mar 19aquasecurity/trivy-action76 GitHub Action tags poisoned, 1,000+ cloud envs infected
Mar 2066+ npm packagesCanisterWorm self-spreading worm with blockchain C2
Mar 23Checkmarx GitHub ActionsCompromised via stolen Trivy CI/CD credentials
Mar 24litellm 1.82.7, 1.82.83.4M daily downloads, .pth credential stealer
Mar 27telnyx 4.87.1, 4.87.2WAV steganography payload, AES-256-CBC exfil (CVE-2026-33634)

Each attack used credentials stolen from the previous one. Trivy was the entry point. LiteLLM was the payload.

Why Existing Tools Missed It

Your usual defenses weren't designed for this:

The attack window was 3 hours. Standard tooling has a 24–48 hour lag minimum.

What CodeGuard Does Differently

CodeGuard Pro is a pre-install security gate. It runs before pip, not after.

codeguard check litellm==1.82.8
$ codeguard check litellm==1.82.8   CodeGuard Pre-Install Check (pypi)   BLOCKED litellm==1.82.8 KNOWN COMPROMISED: TeamPCP supply chain attack — .pth credential stealer (SSH, cloud, crypto, Slack, Discord) Compromised version matched: 1.82.8   BLOCKED: 1 package(s) look dangerous. DO NOT install these. They may be typosquats or malicious.

Safe packages pass cleanly:

codeguard check requests==2.31.0
$ codeguard check requests==2.31.0   CodeGuard Pre-Install Check (pypi)   SAFE requests==2.31.0   All 1 package(s) look safe to install.

What it detects

Compromised packages — a curated database of known-malicious versions, updated as attacks are discovered. Currently includes litellm, telnyx, ultralytics YOLO, ctx, and more.

GitHub Actions supply chain attacks — scans your .github/workflows/ for mutable tag references and known-compromised actions (tj-actions/changed-files CVE-2025-30066, Trivy-action TeamPCP poisoning, Checkmarx).

.pth file injection — detects malicious .pth files in your Python environment that execute code at startup.

Typosquatting — catches packages named to look like popular ones (requestss, pandas-sdk, colorinal).

Secret scanning — 25+ patterns: OpenAI, AWS, Stripe, GitHub, Slack, GCP, private keys, JWTs.

The Red-Team Benchmark

codeguard redteam-demo
$ codeguard redteam-demo   { "summary": { "mocked_install_persistence": { "samples": 6, "blocked": 6, "verdict": "BLOCKED" }, "pinned_package_verdicts": { "litellm==1.82.8": "BLOCKED", "telnyx==4.87.2": "BLOCKED", "requests==2.31.0": "SAFE" } }, "pth_corpus": { "scanned": 6, "findings": 6, "verdict": "BLOCKED" } }   techniques blocked: base64+eval · socket exfil · requests.post · subprocess curl · os.system · WAV stego

6 real attack techniques: base64-obfuscated eval, socket exfiltration, subprocess curl to attacker C2, requests.post of environment variables, WAV steganography decoding. All 6 blocked. Safe packages pass.

How We Built It

CodeGuard started as a simple secret scanner for AI coding agents. Over the last week it evolved fast:

The threat feed is the key piece. Instead of baking IOCs into the binary, there's a hosted feed that updates in real time as new attacks are discovered — without requiring users to reinstall.

How to Use It

quick start
# Install $ pipx install codeguard-pro   # Hook into every git commit $ codeguard install   # Check before installing a package $ codeguard check litellm==1.82.8 BLOCKED litellm==1.82.8 ← TeamPCP .pth stealer   # Scan GitHub Actions for poisoned refs $ codeguard scan .github/workflows/   # MCP config (Claude Code / Cursor / Codex) "mcpServers": { "codeguard": { "command": "codeguard-mcp" } }

The Bigger Picture

The timing of this attack is not coincidental. AI coding agents are writing and installing packages faster than any human review process can keep up with. Cursor, Claude Code, Codex — they all install dependencies on your behalf. None of them, by default, check whether the version they're about to install was compromised 3 hours ago.

CodeGuard closes that gap.


Protect your pipeline

144 tests passing. MIT licensed. MCP compatible. Free to use.

GitHub PyPI Live Feed