TeamPCP’s Supply Chain Campaign So Far..

TeamPCP is the name that stuck to a weeks-long supply-chain compromise that refused to stay in one ecosystem. It started in GitHub Actions, jumped to container registries, spread to npm and PyPI, and eventually landed in OpenVSX. Along the way, researchers connected the same cluster of activity to Aqua's Trivy scanner, Checkmarx's KICS and AST tooling, LiteLLM on PyPI, Telnyx packages, and a self-propagating npm worm that people have been calling CanisterWorm.

The through-line is one we have seen before: stolen or abused credentials, tags, and releases that quietly diverge from clean main-branch history, and second-stage tooling engineered to vacuum up cloud and CI secrets.

How the compromise chain works

The attackers never needed a malicious merge to main. If CI runs on tags and refs, and most pipelines do, the door is already open.

What keeps showing up across every variant of this campaign is the same three-step trick:

  1. Create an orphan or imposter commit, an object that exists in Git's graph because forks and cross-repo references still let automation see it, even though no one ever approved a pull request into the default branch.

  2. Point a tag at that commit.

  3. Watch the pipeline fire. No merge required. No code review. Just a tag pointing somewhere it shouldn't.

Reporting names several of those commits explicitly. actions/checkout at 70379aad was crafted to look like it came from rauchg. aquasecurity/trivy at 1885610c carried fake attribution toward DmitriyLewen. aquasecurity/trivy-action at ddb9da44 rounds out the set most commonly cited for tag-driven workflows. All three SHAs are still on GitHub if you want to diff them yourself.

Lateral movement inside Aqua's org

Once inside, the attackers moved laterally through several Aqua repositories:

  • tfsec (a67fd5b5)

  • traceeshark (56591dfe)

  • trivy-action (93ed4111) — a second malicious cut

  • setup-trivy (8afa9b9f) — attributed to a spoofed identity, thara

Checkmarx Actions

On the Checkmarx side, two Action repos were hit:

  • kics-github-action (121c38f)

  • ast-github-action (aa52a82c)

LiteLLM

The LiteLLM thread is messier, but the shape is identical. BerriAI/litellm (fcaa823d) and litellm-skills (81c851cc) were both altered in ways that touched test.yml — classic workflow exfiltration terrain.

GitHub identities worth tracking

If you are hunting by identity rather than commit SHA, these are the names that keep showing up:

  • aqua-bot (ID 54269356)

  • Argon-DevOps-Mgt (139343333) is tied to the aquasec-com defacement

  • cx-plugins-releases (225848595) the KICS release path

  • octocommit (266895321) formerly DarkSeek3r

  • ast-phoenix, the OpenVSX publisher in the Checkmarx thread

Poisoned container images

The malicious 0.69.4 images sat on three registries simultaneously: ghcr.io/aquasecurity/trivy, docker.io/aquasec/trivy, and public.ecr.aws/aquasecurity/trivy and stayed live for roughly three hours. Versions 0.69.5 and 0.69.6 on Docker Hub, dated 2026-03-22, show up in the same incident notes.

PyPI and npm

On PyPI, the affected packages were litellm versions 1.82.7 and 1.82.8 (both later quarantined) and telnyx versions 4.87.1 and 4.87.2, which were outright malicious. Some write-ups flag a Windows-specific bug in 4.87.1.

On npm, CanisterWorm hit at scale: large batches under @EmilGroup and @opengov, self-propagating copies in @teale.io/eslint-config 1.8.11 and 1.8.12, plus @airtm/uuid-base32 and @pypestream/floating-ui-dom as examples worth blocking if you are still hunting artifacts.

Trivy (Aqua)

v0.69.4 is the tag everyone keeps circling back to. It pointed at a malicious commit, and publishing it required genuine write access, meaning the attacker had real credentials, not just a fork.

Aqua's own account of what happened frames it as incomplete containment after their 2026-03-01 incident. Credential rotation was not atomic, which left a window for attackers to reuse refreshed tokens while the security team thought cleanup was finished.

The scale was enormous: 75 of 76 tags were hijacked. Bad binaries shipped through GitHub Releases, Docker Hub, and npm, with the npm angle tying back to CanisterWorm in broader reporting.

The identity aqua-bot is the one researchers describe pivoting from Trivy into tfsec, traceeshark, and trivy-action. The key commits - 1885610c and 70379aad never touched main. They existed only as orphans. v0.69.4 simply referenced them, and CI dutifully ran the code without a merge or review ever taking place.

There is one loose end that still gets discussed: v0.70.0 was deleted on 2026-03-19 at 17:51:17 UTC. Commit 9dbb34d3ec0f, authored by aqua-bot on 2026-03-16 with the message "Updates," touched main.go, auth.go, repowrite.go, and runner.go. Whether this was part of the same attack or something else remains unclear.

setup-trivy GitHub Action

The setup-trivy compromise followed a tight sequence:

  1. Someone force-pushed seven tags, v0.2.0 through v0.2.6.

  2. Commit 8afa9b9f spoofed thara (Tomochika Hara), claimed to pin the install script checkout, and carried a backdated timestamp of 2026-01-15.

  3. The exposure window was roughly four hours on 2026-03-19 (17:43–21:44 UTC).

Grafana often comes up as a downstream example of who was pulling these tags during that window.

Checkmarx (KICS, AST, OpenVSX, GitHub Actions)

The Checkmarx thread is a three-way compromise: a service account was popped, OpenVSX extensions were hijacked, and GitHub Actions were force-pushed, all in the same campaign. In total, 35 KICS tags and 91 AST tags were redirected to malicious commits. The C2 domain checkmarx.zone keeps appearing throughout this thread.

LiteLLM (BerriAI) on PyPI

This one started with a PyPI token that leaked out of a Trivy-in-CI workflow, a direct consequence of the upstream compromise. Versions 1.82.7 and 1.82.8 were published with credential-stealing payloads and persistence mechanisms baked in.

Someone on vxunderground claimed 54 GB of data was exfiltrated. Treat that number as community chatter, not a verified total.

Telnyx on PyPI

Telnyx's PyPI credentials were also abused. Versions 4.87.1 and 4.87.2 embed WAV-based steganography targeting both Windows and Unix-like systems. Public timelines put the exposure at around four hours before quarantine.

npm (CanisterWorm)

Stolen npm tokens fed a worm that phones home to an ICP canister, a decentralized infrastructure that is harder to take down than a typical C2. One snapshot claims 28+ packages were hit in under a minute across several orgs, with 135+ artifacts across 64+ packages total. Use those numbers as a rough sense of scale, not gospel. Trivy-linked npm malware is discussed in the same breath as this worm, and the infrastructure overlaps are real.

Payload families (analysis repos)

LiteLLM 1.82.8

The best-documented payload is the one in HackingLZ/litellm_1.82.8_payload. The chain works like this:

  • litellm_init.pth fires on interpreter startup and polls roughly every 50 minutes.

  • A sandbox check bounces through youtube.com, a "Bad Apple!!" style connectivity gate.

  • proxy_server.py handles filesystem and cloud token collection.

  • sysmon.py drops into ~/.config/systemd/user/ for persistence, using RSA-wrapped exfiltration.

  • The same 4096-bit RSA public key shows up often enough that analysts treat it as a fingerprint across samples.

LiteLLM 1.82.7

Version 1.82.7 swaps RSA for RC4, keeps the same filenames, points at checkmarx.zone, and reuses the same key family.

Telnyx

Telnyx samples hide payloads in WAV files (hangup.wav, ringtone.wav), drop msbuild.exe on Windows, and run AES-256-CBC with RSA-4096-style chains on Linux and macOS. The key family matches what shows up in LiteLLM reporting. MalwareBazaar carries community submissions tagged teampcp if you want binaries to compare against.

What is settled versus what is still open

Settled

Aqua is on the record that v0.69.4 traces to incomplete containment from 2026-03-01 and non-atomic credential rotation, meaning refreshed tokens could leak while the security team believed they had already finished cleanup. The aqua-bot identity fits neatly into that story.

The setup-trivy force-push window - seven tags, commit 8afa9b9f, roughly four hours on 2026-03-19, is treated as fact in the same disclosures.

Still noisy

Two things remain unresolved in public discussion. The deleted v0.70.0 tag raises questions nobody has publicly answered yet. And whether octocommit (formerly DarkSeek3r) is a coincidence or an actual campaign infrastructure is still unclear.

Myths corrected

A few names keep getting thrown around in connection to this campaign that do not actually belong here:

  1. hackerbot-claw is not the main character. It is an automated pentest bot whose behavior and user-agent do not align with the cluster Aqua cares about for aqua-bot PAT theft.

  2. MegaGame10418 is the name tied to the 2026-02-27 PwnRequest path that exfiltrated Aqua-bot's token. This comes from Aqua's own postmortem - it is a specific attribution, not a rumor.

  3. The malicious objects never needed main. This is probably the most important misconception to correct. v0.69.4 pointed at orphan commits, and CI ran them anyway. No merge. No review.

  4. GhostClaw is a different campaign entirely: npm typosquatting, AI workflow hooks, different infrastructure. IOCs do not overlap with TeamPCP in any reporting so far.

Actor and targets

Researchers bucket the actor under several names: TeamPCPPCPcatPersy_PCPShellForceCipherForce, and DeadCatx3. Telegram handles @Persy_PCP and @teampcp float around open-source intelligence channels.

Their targeting reads like a cloud-native checklist: Docker, Kubernetes, GitHub Actions, Ray, Redis, and CI/CD infrastructure broadly. Tactically, the playbook mixes supply-chain poisoning with opportunistic scanning of exposed services, /proc scraping, wide filesystem sweeps, IMDS queries, typosquats, Cloudflare tunnels for exfil, GitHub repos as dead drops, and ICP canisters as fallback infrastructure. The end goals in the same reporting range from lateral movement to ransomware, mining, and extortion.

One defensive oddity worth noting: researchers have mapped a timeline of song titles to attacker hostnames: scan.aquasecurtiy.org, checkmarx.zone, nsa.cat, and others. Whether that is operational creativity or just someone having fun naming things, it makes for a distinctive fingerprint. MalwareBazaar still indexes teampcp samples if you want hands-on material to compare.

References:

Next
Next

How an AI Gateway can secure your LLMs