TL-2026-0281 CRITICAL 2026-03-25 Campaign Report

TeamPCP Supply Chain Campaign — Trivy, LiteLLM, and the 5-Day Multi-Ecosystem Siege

Threadlinqs Intel Team 12 min
teampcpsupply-chaintrivylitellmnpm-wormgithub-actionscve-2026-33634pypicanisterwormkicskubernetes-wipericp-c2

Threat ID: TL-2026-0281 | Severity: CRITICAL | CVE: CVE-2026-33634

Actor: TeamPCP | Motivation: DESTRUCTIVE / CREDENTIAL THEFT

Related Reports: 9 | Available Detections: 81+


Between March 19 and March 24, 2026, a threat actor operating under the moniker TeamPCP executed one of the most sophisticated multi-ecosystem supply chain attacks documented to date. The campaign simultaneously compromised Aqua Security's Trivy vulnerability scanner, BerriAI's LiteLLM AI proxy, Checkmarx's KICS GitHub Action, and propagated a self-replicating worm across 66+ npm packages — affecting CI/CD pipelines, Python environments, and Kubernetes clusters globally.

The scope of this operation is notable not for any single novel technique, but for the coordinated execution across five distinct software ecosystems within a compressed timeframe. TeamPCP exploited residual access from an earlier compromise of the hackerbot-claw VS Code extension (TL-2026-0165), demonstrating how incomplete credential rotation following a security incident can cascade into a much larger event. This article traces the full attack timeline across 9 related threat intelligence reports, provides detection guidance, and maps the campaign to MITRE ATT&CK.

Executive Summary

Technical Analysis

The TeamPCP campaign unfolded in five distinct phases over a 25-day span (Feb 28 – Mar 24), each building on access obtained in the previous phase. The operational pattern suggests a single coordinated actor or small group with pre-positioned access across multiple package registries and CI/CD platforms.

Phase 1: The Genesis — VS Code Extension Compromise (February 28)

The campaign's origin traces to TL-2026-0165, in which the hackerbot-claw VS Code extension was compromised via a stolen Personal Access Token (PAT) belonging to an Aqua Security developer. The attacker published a malicious version to the OpenVSX registry. Aqua Security responded with a credential rotation, but the rotation was incomplete. Residual access to GitHub Actions workflows and associated service accounts remained valid. This gap — between incident response and full credential invalidation — provided TeamPCP the foothold required for everything that followed.

The takeaway is straightforward: credential rotation after a compromise must be exhaustive and verified. A partial rotation is indistinguishable from no rotation if the adversary retains even one valid token.

Phase 2: Trivy Ecosystem Takeover (March 19–20)

TeamPCP used the residual access to compromise the Trivy GitHub Actions ecosystem across three vectors, documented in TL-2026-0256, TL-2026-0263, and TL-2026-0270.

The actor force-pushed 75 of 76 trivy-action tags and all 7 setup-trivy tags to malicious commits. The single uncompromised trivy-action tag appears to have been protected by a branch protection rule that the stolen credentials could not override. The compromised entrypoint.sh script expanded from a legitimate 2,855 bytes to a malicious 17,592 bytes (204 lines), containing:

Simultaneously, the Trivy v0.69.4 binary release was compromised on Docker Hub. Any CI/CD pipeline pulling aquasecurity/trivy-action@v1 (or any floating tag) between March 19 and the remediation window ingested the malicious payload. Given Trivy's position as one of the most widely adopted open-source vulnerability scanners, the blast radius was substantial.

Phase 3: CanisterWorm npm Propagation (March 20–22)

Documented in TL-2026-0259, a self-propagating npm worm — internally dubbed CanisterWorm — compromised 29 packages in its initial wave, expanding to 66+ packages across the @emilgroup and @teale.io scopes. The propagation mechanism was credential-based: stolen npm publisher tokens from Phase 2's credential harvesting were used to authenticate to the npm registry and publish trojanized versions of packages maintained by the compromised accounts.

The worm's payload included Python implants with systemd persistence masquerading as sysmon.service — a naming choice designed to blend with environments where administrators might expect Sysmon-like tooling. The implants phoned home to Internet Computer Protocol (ICP) blockchain canisters, representing the first documented use of ICP canisters as C2 dead drops in a supply chain attack. The canister at tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io served as an immutable, censorship-resistant coordination point that could not be taken down through traditional domain seizure or hosting provider abuse reports.

Phase 4: LiteLLM PyPI Compromise (March 22)

The core of TL-2026-0281. TeamPCP published trojanized versions of BerriAI's LiteLLM package — v1.82.7 and v1.82.8 — to PyPI. LiteLLM is an AI proxy that abstracts multiple LLM provider APIs behind a unified interface, making it a high-value target given the concentration of API keys in its deployment environments.

The trojanized versions implemented a multi-stage credential stealer:

The choice of LiteLLM as a target reflects an understanding of the current software landscape. AI/ML infrastructure frequently holds credentials for multiple cloud providers, model APIs, and data stores. Compromising a single AI proxy package yields access to a dense cluster of high-value secrets.

Phase 5: KICS GitHub Action and Kubernetes Wiper (March 23–24)

The campaign's final phase, documented in TL-2026-0274 and TL-2026-0279, shifted from credential theft to destructive operations. TeamPCP hijacked 35 Checkmarx KICS release tags on GitHub, injecting payloads that deployed Kubernetes DaemonSets onto any cluster accessible from the compromised CI/CD runner.

Two DaemonSet variants were observed:

Both DaemonSets requested privileged pod security contexts, enabling host PID namespace access, host networking, and the ability to read and write arbitrary host paths. In Kubernetes clusters without Pod Security Admission enforcement, these DaemonSets deployed silently across all nodes.

Novel Techniques

Several aspects of this campaign represent documented firsts or rare operational patterns worth highlighting for defenders:

Detection

Threadlinqs Intelligence provides 81+ production-ready detection rules across 9 threat reports covering this campaign. The detection strategy spans three layers: CI/CD pipeline integrity monitoring, endpoint credential access detection, and Kubernetes runtime anomaly detection. Below are three representative rules.

Splunk SPL — Python .pth File Injection in Site-Packages

This rule detects the creation of .pth files in Python site-packages directories, excluding known legitimate entries created by pip and setuptools. The LiteLLM trojan dropped a .pth file to achieve interpreter-level persistence — any new .pth file outside of a known package installation workflow warrants investigation.

SPLindex=* sourcetype=sysmon EventCode=11
| where match(TargetFilename, "site-packages.*\\.pth$")
| where NOT match(TargetFilename, "(setuptools|pip|easy-install)\\.pth")
| stats count by TargetFilename, Image, ComputerName

Sysmon EventCode 11 (FileCreate) is the primary data source. False positives are limited to legitimate Python package installations that create .pth files, which should be baselined in environments with known package management workflows.

Microsoft KQL — /proc/*/mem Reads in CI/CD Environments

The Trivy compromise scraped GitHub Actions runner memory via /proc/*/mem to extract secrets. This KQL query detects file reads targeting process memory files from shell or Python interpreters — behavior that should never occur in a standard CI/CD runner execution.

KQLDeviceFileEvents
| where ActionType == "FileRead"
| where FolderPath matches regex @"/proc/\d+/mem"
| where InitiatingProcessFileName in ("bash", "sh", "python3")
| project Timestamp, DeviceName, InitiatingProcessCommandLine, FolderPath

Any process reading /proc/<pid>/mem from a CI/CD runner context is inherently suspicious. Legitimate debugging tools (gdb, strace) may trigger this in development environments but should not appear in production pipeline runners.

Sigma — TeamPCP Cloudflare Tunnel C2 Communication

TeamPCP used Cloudflare's quick tunnel service (.trycloudflare.com) for C2 communication. This Sigma rule matches DNS queries to the specific tunnel subdomains observed in the campaign. The subdomain naming pattern uses four hyphenated English words generated by Cloudflare's tunnel provisioning system.

SIGMAtitle: TeamPCP Cloudflare Tunnel C2 Communication
id: a7c3e9f1-2b8d-4f6a-9e1c-3d5f7a8b2c4e
status: experimental
description: |
    Detects DNS resolution for Cloudflare quick tunnel subdomains associated
    with TeamPCP supply chain campaign C2 infrastructure (CVE-2026-33634).
references:
    - https://intel.threadlinqs.com/#TL-2026-0281
    - https://intel.threadlinqs.com/#TL-2026-0256
author: Threadlinqs Intelligence
date: 2026/03/25
tags:
    - attack.command_and_control
    - attack.t1102.001
    - attack.t1572
    - attack.t1071.001
logsource:
    category: dns
    product: any
detection:
    selection:
        query|endswith: '.trycloudflare.com'
    filter:
        query|contains:
            - 'championships-peoples-point-cassette'
            - 'investigation-launches-hearings-copying'
            - 'souls-entire-defined-routes'
            - 'plug-tab-protective-relay'
    condition: selection and filter
falsepositives:
    - Legitimate Cloudflare tunnel usage with coincidentally matching subdomain names (extremely unlikely)
level: critical
Browse all 81+ detection rules across 9 related threat reports: View on Threadlinqs Intelligence

Indicators of Compromise

Network Indicators

TypeIndicatorContext
Domainscan.aquasecurtiy.orgTyposquatted C2 domain (note: "securtiy" misspelling)
Domainmodels.litellm.cloudLiteLLM credential exfiltration endpoint
Domaincheckmarx.zoneKICS campaign C2 and DaemonSet staging
IP45.148.10.212Primary C2 server (TECHOFF SRV, Amsterdam, NL)
ICP Canistertdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.ioBlockchain dead drop for CanisterWorm coordination
CF Tunnelchampionships-peoples-point-cassette.trycloudflare.comCloudflare quick tunnel C2 channel 1
CF Tunnelinvestigation-launches-hearings-copying.trycloudflare.comCloudflare quick tunnel C2 channel 2
CF Tunnelsouls-entire-defined-routes.trycloudflare.comCloudflare quick tunnel C2 channel 3
CF Tunnelplug-tab-protective-relay.trycloudflare.comCloudflare quick tunnel C2 channel 4

Affected Package Versions

PackageVersion / ScopeEcosystemStatus
litellm1.82.7, 1.82.8PyPIYanked
trivy0.69.4Docker Hub / GitHub ReleasesReverted
trivy-action75 of 76 release tagsGitHub ActionsTags re-signed
setup-trivyAll 7 release tagsGitHub ActionsTags re-signed
kics-github-action35 release tagsGitHub ActionsTags re-signed
@emilgroup/*29+ packagesnpmUnpublished
@teale.io/*37+ packagesnpmUnpublished

File and Behavioral Indicators

TypeIndicatorContext
Fileentrypoint.sh (17,592 bytes / 204 lines)Malicious trivy-action entrypoint
File*.pth in site-packages (non-standard)LiteLLM Python startup persistence
Systemdsysmon.serviceCanisterWorm persistence unit (masquerading)
K8s DaemonSethost-provisioner-iranDestructive wiper targeting Iranian infrastructure
K8s DaemonSethost-provisioner-stdGeneral-purpose backdoor DaemonSet
K8s Pod prefixnode-setup-*Backdoor pod naming pattern
ProcessReads to /proc/*/mem from shell processesRunner memory scraping for secrets

Timeline

DateEventReference
2026-02-28hackerbot-claw VS Code extension compromised via stolen PAT; malicious version published to OpenVSXTL-2026-0165
2026-03-01Aqua Security initiates credential rotation (incomplete — residual access persists)TL-2026-0165
2026-03-19TeamPCP force-pushes 75/76 trivy-action tags and 7/7 setup-trivy tags to malicious commitsTL-2026-0256
2026-03-19Compromised entrypoint.sh begins harvesting credentials and reading runner memory via /proc/*/memTL-2026-0263
2026-03-20Trivy v0.69.4 binary release compromised on Docker HubTL-2026-0270
2026-03-20CanisterWorm initial wave compromises 29 npm packages across @emilgroup scopeTL-2026-0259
2026-03-21CanisterWorm spreads to @teale.io scope; total reaches 50+ packagesTL-2026-0259
2026-03-22Trojanized LiteLLM v1.82.7 published to PyPI with .pth persistence and hybrid-encrypted exfiltrationTL-2026-0281
2026-03-22LiteLLM v1.82.8 published with identical payload; npm worm count exceeds 66 packagesTL-2026-0281
2026-03-2335 Checkmarx KICS GitHub Action release tags hijackedTL-2026-0274
2026-03-23Destructive Kubernetes DaemonSets (host-provisioner-iran, host-provisioner-std) begin deploying from compromised pipelinesTL-2026-0279
2026-03-24Aqua Security, BerriAI, and Checkmarx issue coordinated security advisories; compromised packages yanked/revertedCVE-2026-33634
2026-03-25CVE-2026-33634 assigned; CVSS score pending; community-wide credential rotation campaigns underwayThis report

MITRE ATT&CK Mapping

TacticTechniqueIDCampaign Usage
Initial AccessSupply Chain Compromise: Software Supply ChainT1195.002Poisoned trivy-action tags, LiteLLM PyPI packages, KICS Action, and 66+ npm packages
ExecutionCommand and Scripting InterpreterT1059Malicious entrypoint.sh (bash), Python .pth loaders, npm postinstall scripts
Credential AccessUnsecured CredentialsT1552Enumeration of 50+ credential file paths (AWS, GCP, Azure, Docker, Kube, SSH, npm, PyPI)
ExfiltrationExfiltration Over Web ServiceT1567.001Credential exfiltration to Cloudflare tunnel endpoints and typosquatted domains
Command and ControlWeb Service: Dead Drop ResolverT1102.001ICP blockchain canisters as immutable C2 coordination points
Command and ControlAsymmetric CryptographyT1573.002AES-256-CBC + RSA-4096 hybrid encryption for exfiltrated credential payloads
PersistenceCreate or Modify System Process: Systemd ServiceT1543.002sysmon.service systemd unit for CanisterWorm persistence on Linux hosts
ExecutionDeploy ContainerT1610Privileged Kubernetes DaemonSets deployed from compromised CI/CD pipelines
Privilege EscalationEscape to HostT1611Privileged pod security context enabling host filesystem and PID namespace access
ImpactData DestructionT1485host-provisioner-iran DaemonSet executing destructive wipe operations
Defense EvasionDeobfuscate/Decode Files or InformationT1140Double base64-encoded payload in .pth files to evade static analysis
Full MITRE ATT&CK mapping across all 9 related threats: View coverage on Threadlinqs

Recommendations

  1. Pin GitHub Actions to full commit SHAs, never floating tags. This campaign would have had no impact on pipelines that pinned aquasecurity/trivy-action and checkmarx/kics-github-action to specific commit hashes rather than version tags. Tags are mutable references — SHAs are not. Audit all workflow files for tag-based references and replace them with pinned commits. Tools such as pinact can automate this across repositories.
  2. Audit Python .pth files in all site-packages directories. Run find / -name "*.pth" -path "*/site-packages/*" 2>/dev/null and verify every entry against known legitimate packages (setuptools, pip, easy-install). Any .pth file that was not created by a recognized package manager installation is a persistence indicator requiring immediate investigation.
  3. Verify Trivy binary checksums against Aqua Security's security advisory. If your environment pulled Trivy v0.69.4 between March 19 and March 24, treat the binary as compromised. Re-download from a verified source and compare SHA-256 hashes against the values published in Aqua's advisory. Rebuild any container images that embedded the compromised binary.
  4. Block IOC domains at DNS and proxy level. Add scan.aquasecurtiy.org, models.litellm.cloud, checkmarx.zone, and the four .trycloudflare.com subdomains to DNS sinkholes and web proxy block lists. Monitor for historical resolution of these domains in DNS logs to identify previously compromised systems.
  5. Monitor Kubernetes clusters for unauthorized privileged DaemonSets. Alert on any DaemonSet creation requesting privileged security context, host PID namespace, or host filesystem mounts that does not match an approved allowlist. Pod names matching node-setup-* or host-provisioner-* patterns warrant immediate investigation. Enforce Pod Security Admission at the Restricted level where operationally feasible.

References


Full threat intelligence, detection rules, and IOC feeds are available on Threadlinqs Intelligence. Track this threat: TL-2026-0281.

HB

Threadlinqs Intel Team

Threat Intelligence Analyst

Hatim covers supply chain security, CI/CD pipeline threats, and adversary infrastructure at Threadlinqs Intelligence. He tracks threat actor campaigns across package ecosystems and cloud-native environments, translating observed tradecraft into production-ready detection engineering.