system: OPERATIONAL
← back to all hacks
SUPPLY CHAIN CRITICAL NEW

LiteLLM backdoored: when a poisoned CI scanner takes over the LLM gateway

In March 2026, attackers stole LiteLLM's PyPI publishing token by compromising Trivy inside its CI pipeline, then shipped two backdoored releases. The chain shows why the LLM gateway is a high-value supply-chain target.

2026-06-17 // 7 min affects: litellm, trivy, checkmarx-kics, crewai, dspy, mlflow

What happened

On March 24, 2026, two malicious versions of the litellm Python package — 1.82.7 and 1.82.8 — were published to PyPI by a threat actor tracked as TeamPCP. LiteLLM is the model-gateway library that sits under CrewAI, DSPy, MLflow, OpenHands and dozens of other agent frameworks, and is pulled millions of times a day. The packages were live for roughly three hours before PyPI quarantined them, per Snyk’s analysis and Help Net Security.

The attackers never exploited a flaw in LiteLLM’s own code. They obtained the project’s PYPI_PUBLISH token by first compromising Trivy, an open-source scanner that ran inside LiteLLM’s CI pipeline. This is a textbook tool-chain attack: poison a trusted build dependency, harvest the credential it can see, and publish a legitimately-signed malicious release.

How it works

The chain unfolded over five days, and each hop reused the same exfiltration infrastructure (a shared RSA key and a tpcp.tar.gz bundle name confirmed across operations by Wiz and Unit 42):

  • Mar 19 — TeamPCP rewrote Git tags in the trivy-action repository to point a version tag at a malicious release, after stealing Aqua’s automation credentials via a pull_request_target “Pwn Request” workflow that checks out and runs untrusted fork code.
  • Mar 23 — The same playbook hit Checkmarx KICS; the C2 domain checkmarx.zone and the exfil domain models.litellm.cloud were registered.
  • Mar 24 — LiteLLM’s CI ran the poisoned Trivy from apt without a pinned version. The compromised action read the PYPI_PUBLISH token from the runner environment, and the attackers used it to publish the two backdoored releases.

The payload itself was a three-stage credential stealer: harvest secrets (SSH keys, .env files, cloud and Kubernetes credentials, wallet seeds), encrypt and POST them to the exfil domain, then install a systemd user service for persistence and attempt lateral movement across Kubernetes namespaces. Version 1.82.8 escalated delivery with a .pth startup hook — a file in site-packages/ that executes on every Python interpreter launch, including pip install itself, with no import required. Because the package was signed with stolen-but-legitimate credentials, it passed pip hash verification cleanly. We deliberately omit the payload internals; the defensive takeaways below do not require them.

A notable wrinkle: part of the campaign’s targeting was driven by an autonomous attack bot. StepSecurity documented hackerbot-claw, a GitHub account describing itself as an “autonomous security research agent,” that scanned repositories and opened exploit pull requests against Microsoft, DataDog and CNCF projects over a 10-day window — one of the first observed cases of an AI agent operationally driving supply-chain intrusions.

Why this matters

The LLM gateway is becoming the single most concentrated credential store in an AI stack. A router like LiteLLM is, by design, given API keys for every model provider it fronts, plus the environment of whatever host runs it. Compromise that one position and you intercept secrets for the whole fleet without breaching any upstream provider — exactly the leverage TeamPCP went after. Help Net Security and Unit 42 both note the broader pattern: the campaign deliberately targeted security tools (Trivy, Checkmarx) because scanners hold broad read access to the pipelines they run in. Your defensive tooling is part of your attack surface.

Defenses

  • Pin every CI dependency by digest, not tag. Git tags are mutable; pin GitHub Actions and CLI tools to a commit SHA or content hash so a rewritten tag cannot silently swap in a malicious release.
  • Lock down pull_request_target. Never check out and execute untrusted fork code in a privileged workflow. Use pull_request for fork CI, gate privileged jobs behind manual approval, and scope GITHUB_TOKEN to read-only.
  • Constrain publishing credentials. Prefer short-lived, OIDC-based PyPI Trusted Publishing over long-lived PYPI_PUBLISH tokens, and isolate the publish step from steps that run third-party tools.
  • Monitor build-time network egress. Allowlist outbound destinations from runners so an unexpected curl to an unknown domain is blocked and alerted, not silently executed.
  • Detect .pth startup hooks. Hash verification alone won’t catch a maliciously-published-but-validly-signed package. Flag any dependency that installs a .pth file containing exec, subprocess or base64.
  • If you ran 1.82.7 or 1.82.8: treat the host as compromised, pin to <=1.82.6 (or a clean later release), rotate all reachable credentials, and hunt for the persistence service and Kubernetes pods named node-setup-*.

Status

ItemState
Affected litellm versions1.82.7, 1.82.8 — quarantined and removed from PyPI
Safe versions≤ 1.82.6, plus clean releases after key rotation (Mar 24)
Root causeStolen PYPI_PUBLISH token via poisoned Trivy in CI
DisclosureFutureSearch raised the alarm Mar 24, 2026; keys rotated same day
Wider campaignTeamPCP also hit Trivy (Mar 19) and Checkmarx KICS (Mar 23)

Dates and technical details drawn from Snyk (Mar 24, 2026), Help Net Security (Mar 25, 2026), Palo Alto Unit 42 and StepSecurity. Package versions and infrastructure indicators reflect those vendors’ published findings.

Sources