TeamPCP Supply Chain Campaign

TeamPCP Supply Chain Campaign


What Happened — The Attack Chain

This is a deliberate, multi-hop campaign, not opportunistic. The attack on LiteLLM started five days earlier with Trivy. On March 19, attackers rewrote Git tags in the trivy-action GitHub Action repository to point to a malicious release (v0.69.4) carrying a credential-harvesting payload. On March 23, the same infrastructure was used in a separate attack on Checkmarx KICS. On March 24, LiteLLM’s CI/CD pipeline ran Trivy as part of its build process, pulling it from apt without a pinned version — the compromised action exfiltrated the PyPI publish token from the GitHub Actions runner environment.

Each compromise unlocked the next. The Sysdig Threat Research Team observed that stolen credentials from the Trivy compromise were used to poison additional actions in affected repositories — suggesting credential pivoting as the core propagation technique.

The Payload — Three-Stage Architecture

The payload is a three-stage attack: a credential harvester sweeping SSH keys, cloud credentials, Kubernetes secrets, cryptocurrency wallets, and .env files; a Kubernetes lateral movement toolkit deploying privileged pods to every node; and a persistent systemd backdoor (sysmon.service) polling checkmarx[.]zone/raw for additional binaries. Harvested data is exfiltrated as an encrypted archive (tpcp.tar.gz) to a C2 domain named models.litellm[.]cloud via HTTPS POST.

The systemd persistence script polls the C2 every 5 minutes for a URL. If the URL contains youtube[.]com, the script aborts — a kill switch. The endpoint was returning YouTube URLs at time of analysis, meaning the operator can switch to live payloads at will. If the script finds a Kubernetes service account token, it reads all secrets across every namespace, then attempts to deploy a privileged pod to every node in kube-system using alpine:latest.

LiteLLM — Why It Was a High-Value Target

Environments running LiteLLM typically store multiple API keys for providers such as OpenAI, Anthropic, and others in one place, making it a high-value target for credential harvesting.

LiteLLM is downloaded roughly 3.4 million times per day. The malicious versions were available for approximately three hours before PyPI quarantined the package.

The version 1.82.8 package is the more dangerous of the two. Version 1.82.8 includes a new litellm_init.pth file inside the wheel — meaning the malware runs every single time Python starts on the machine, even if the LiteLLM tool itself is never opened.

Critically, the package passes all standard integrity checks because the malicious content was published using legitimate credentials — no hash mismatch, no suspicious domains, no misspelled package name.

Checkmarx — Scope of Compromise

On March 23, a similar incident was discovered in Checkmarx KICS GitHub Action and Checkmarx AST. TeamPCP also compromised OpenVSX extensions cx-dev-assist 1.7.0 and ast-results. Neither of the malicious packages was published to the VS Code Marketplace

The attack used the same RSA public key as the Trivy operation, allowing Wiz to assess with high confidence it is the same actor.

LAPSUS$ Connection

In what appears to be a further escalation, TeamPCP is said to be collaborating with the notorious extortion group LAPSUS$.

Detection — What Worked and What Didn’t

Static analysis and dependency scanning failed because the malicious code was injected into trusted, signed actions. Network-based detection failed because the typosquat domains were newly registered with clean reputation scores. Runtime detection succeeded — the attacker must ultimately execute system calls to steal and exfiltrate data, and those are observable regardless of delivery mechanism. The highest-signal rule: correlating IMDS access with subsequent data upload from the same process lineage.

Immediate Response Actions

Use only clean versions: Trivy 0.69.7, Checkmarx plugins 1.10.0 or 2.56.0, LiteLLM 1.82.9 or higher. Rotate all cloud credentials, SSH keys, and tokens used between March 19–24. Check for a folder or repository named “tpcp-docs” — its presence is a confirmed indicator of data theft. Pin tools to a SHA hash going forward.

Customers using LiteLLM Cloud or the official LiteLLM Proxy Docker image were not affected due to strict version locking.

The Bigger Picture

Wiz head of threat exposure Gal Nagli framed it directly: Trivy gets compromised → LiteLLM gets compromised → credentials from tens of thousands of environments end up in attacker hands → and those credentials lead to the next compromise. “This campaign is almost certainly not over,” said Endor Labs. “TeamPCP has demonstrated a consistent pattern: each compromised environment yields credentials that unlock the next target.”

TeamPCP has now operated across five ecosystems: GitHub Actions, Docker Hub, npm, Open VSX, and PyPI.

IOCs to monitor:

  • Domains: checkmarx[.]zone, models.litellm[.]cloud, scan.aquasecurtiy[.]org
  • Archive marker: tpcp.tar.gz
  • Systemd service: sysmon.service / ~/.config/sysmon/sysmon.py
  • Kubernetes pod names: node-setup-*, containers named kamikaze or provisioner
  • Repo defacement marker: tpcp-docs-* prefix

Comments

No comments yet. Why don’t you start the discussion?

    Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.