Skip to content

WARNING

Disclaimer: This is OSINT summarized by AI. Trust, but verify.

TeamPCP Supply Chain Campaign (March 2026)

Date: 2026-04-07 TLP: CLEAR Severity: CRITICAL Last Updated: 2026-04-07


Executive Summary

TeamPCP (aliases: PCPcat, Persy_PCP, ShellForce, CipherForce, DeadCatx3) executed one of the most significant open-source supply chain attack campaigns in history during March 2026. Beginning with the compromise of Aqua Security's Trivy vulnerability scanner on March 19, the group cascaded access through Checkmarx KICS, BerriAI LiteLLM, the Telnyx Python SDK, and 47+ npm packages — weaponizing the very security tools organizations rely on. The campaign harvested cloud credentials, CI/CD secrets, and Kubernetes tokens from an estimated 500,000+ machines. CERT-EU attributed the breach of the European Commission's AWS infrastructure (92 GB exfiltrated) to TeamPCP with high confidence. The group partnered with Vect ransomware-as-a-service for monetization and deployed a self-replicating worm (CanisterWorm) with destructive wiper capabilities. CVE-2026-33634 (CVSS 9.4 Critical) was assigned and added to CISA's Known Exploited Vulnerabilities catalog with a remediation deadline of April 8, 2026.


Threat Actor Profile

  • Name: TeamPCP
  • Aliases: PCPcat, Persy_PCP, ShellForce, CipherForce, DeadCatx3
  • Telegram: @Persy_PCP, @teampcp
  • Motivation: Financial (credential theft, ransomware, cryptomining, extortion)
  • Sophistication: Advanced — multi-stage payloads, WAV steganography, ICP-hosted C2, cascading supply chain compromise
  • Partnerships: Vect ransomware group (RaaS), announced via BreachForums; CipherForce (breach data publication)
  • OPSEC: Low — uses identifiable open-source tools (TruffleHog, Nord Stream), obvious resource names ("pawn", "massive-exfil"), prioritizes speed over stealth

Campaign Timeline

DateEvent
Late Feb 2026PwnRequest vulnerability exploited; aqua-bot PAT exfiltrated from Trivy repo
2026-03-19 17:43 UTCMalicious Trivy v0.69.4 released; 76 of 77 trivy-action tags force-pushed to credential-stealing malware
2026-03-21Checkmarx KICS compromised — all 35 tags + v2.3.28 via stolen GitHub PATs
2026-03-22 13:15 UTCCanisterWorm begins propagating through npm ecosystem
2026-03-22 21:40 UTCMalicious Docker Hub images published (Trivy v0.69.5, v0.69.6)
2026-03-23LiteLLM CEO Krish Dholakia's GitHub account compromised; destructive wiper component deployed targeting Iran
2026-03-23Checkmarx GitHub Actions (ast-github-action, kics-github-action) compromised via stolen CI/CD secrets
2026-03-24 ~14:00 UTCMalicious LiteLLM v1.82.7 & v1.82.8 published to PyPI; checkmarx.ast-results v2.53 and checkmarx.cx-dev-assist v1.7.0 published to Open VSX
2026-03-24European Commission breach discovered (access began March 19); 72-minute detection-to-quarantine for LiteLLM on PyPI
2026-03-26CISA adds CVE-2026-33634 to KEV catalog
2026-03-27 03:51 UTCMalicious Telnyx SDK v4.87.1 & v4.87.2 published to PyPI
2026-03-28EU stolen data appears on ShinyHunters' dark web site
Late MarchVect ransomware partnership announced on BreachForums; ~300,000 affiliates receive individual keys

Attack Chain

Phase 1 — Initial Access (Trivy)

TeamPCP exploited incomplete credential rotation from a minor February breach to retain the aqua-bot service account PAT. They force-pushed 76 of 77 version tags in aquasecurity/trivy-action and all 7 tags in aquasecurity/setup-trivy to credential-stealing commits. A malicious Trivy binary (v0.69.4) was published via spoofed commits impersonating users rauchg and DmitriyLewen.

Phase 2 — Cascading Compromise (KICS, LiteLLM)

Credentials harvested from Trivy CI/CD runners were used to compromise Checkmarx KICS GitHub Actions and the personal GitHub account of LiteLLM CEO Krish Dholakia. Malicious LiteLLM packages (v1.82.7, v1.82.8) were pushed to PyPI containing a three-stage payload: orchestrator (.pth file), credential collector, and persistence backdoor.

Phase 3 — Ecosystem Expansion (Telnyx, npm)

PyPI credentials stolen from prior compromises enabled the Telnyx Python SDK compromise. A new TTP was introduced: WAV audio file steganography for payload delivery, with platform-specific payloads (Windows: msbuild.exe dropper; Linux/macOS: credential harvester). 47+ additional npm packages were poisoned via harvested publishing tokens.

Phase 4 — Post-Compromise & Monetization

Stolen credentials were validated at scale using TruffleHog. AWS environments were systematically enumerated and exfiltrated (S3, Secrets Manager, RDS, ECS). The CanisterWorm worm component enabled self-replication through Docker API scanning, SSH key harvesting, and Kubernetes DaemonSet deployment. Partnership with Vect RaaS provided ransomware and extortion capability. 16+ victim organizations were publicly leaked; AstraZeneca was named as a victim (unconfirmed).


Malware Analysis

TeamPCP Cloud Stealer — Three Versions

Version 1 — Monolithic Bash (150 lines)

  • Environment fingerprinting
  • AWS/GCP/Azure IMDS credential harvesting
  • Memory scraping via /proc/<pid>/mem to bypass GitHub secret masking (searches for {"value":"<secret>","isSecret":true})
  • Filesystem sweep of 50+ credential paths (~/.ssh/id_rsa, ~/.aws/credentials, ~/.kube/config, .env files)
  • AES-256-CBC encryption with RSA-4096 key wrapping
  • Exfiltration to C2 as tpcp.tar.gz
  • Fallback: create tpcp-docs repository in victim's GitHub account

Version 2 — Modular Loader (15-line pull-based)

  • Downloads kube.py payload from C2
  • Self-deletion (rm "$0")
  • Remote payload updates without re-poisoning packages

Version 3 — CanisterWorm (Worm & Wiper)

  • Self-replication via Docker API scanning (port 2375)
  • SSH key harvesting for lateral movement
  • Kubernetes cluster targeting via DaemonSet deployment
  • Destructive wiper payload (deployed March 23, targeting Iran)
  • C2 via Internet Computer Protocol (ICP) canister — decentralized, tamper-proof
  • Masquerades as systemd services (sysmon.service) and PostgreSQL utilities (pgmon, pglog)

LiteLLM Payload — Three-Stage Architecture

StageFileBehavior
Orchestratorlitellm_init.pth (34 KB)CPython .pth auto-execution; 50-minute C2 polling; YouTube link anti-sandbox check
Collectorproxy_server.pyTargets 50+ credential file paths; IMDS theft; K8s service account token extraction
Persistencesysmon.py at ~/.config/systemd/user/sysmon.pySystemd user service; polls ICP-hosted C2; downloads payloads to /tmp/pglog

Telnyx Payload — WAV Steganography

Payloads embedded in .wav files that blend with Telnyx's voice/telecom API purpose:

  • Windows: hangup.wav → XOR-decrypted msbuild.exe dropped to Startup folder
  • Linux/macOS: ringtone.wav → AES-256-CBC + RSA-4096 credential sweeper matching LiteLLM pattern
  • Same RSA-4096 public key and tpcp.tar.gz exfiltration pattern across all variants (strongest attribution link)

Obfuscation Techniques

  • LiteLLM v1.82.7: Base64 + zlib, RC4-encrypted strings
  • LiteLLM v1.82.8: Evolved RC4 obfuscation
  • Telnyx: WAV steganography with platform-specific XOR/AES decryption
  • Double Base64 encoding in earlier payloads

Indicators of Compromise

All IOCs are defanged per standard practice.

Command & Control Domains

DomainContext
scan[.]aquasecurtiy[.]orgPrimary C2 for Trivy payload (typosquat of aquasecurity)
checkmarx[.]zoneC2 for KICS & VSX payloads
checkmarx[.]zone/vsxExfiltration endpoint for VS Code extensions
models[.]litellm[.]cloudC2 for LiteLLM payload
nsa[.]catAttacker VPS
tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]ioICP-hosted fallback C2

Cloudflare Tunnel C2 (Ephemeral)

URL
championships-peoples-point-cassette[.]trycloudflare[.]com
create-sensitivity-grad-sequence[.]trycloudflare[.]com
investigation-launches-hearings-copying[.]trycloudflare[.]com
plug-tab-protective-relay[.]trycloudflare[.]com
souls-entire-defined-routes[.]trycloudflare[.]com

IP Addresses

IPContext
23[.]142[.]184[.]129C2 infrastructure
45[.]148[.]10[.]212Resolves from scan[.]aquasecurtiy[.]org (TECHOFF SRV LIMITED, Amsterdam)
63[.]251[.]162[.]11C2 infrastructure
83[.]142[.]209[.]11C2 infrastructure
83[.]142[.]209[.]203C2 for Telnyx compromise
195[.]5[.]171[.]242C2 infrastructure
209[.]34[.]235[.]18C2 infrastructure
212[.]71[.]124[.]188C2 infrastructure
103[.]75[.]11[.]59Referenced in Kudelski research

Post-Compromise Operational IPs (Wiz)

IPASNActivity
105[.]245[.]181[.]120VodacomTruffleHog secret validation
138[.]199[.]15[.]172Mullvad VPNGitHub exfiltration, AWS ops
154[.]47[.]29[.]12Mullvad VPNSecret validation, AWS recon
163[.]245[.]223[.]12InterserverGitHub exfiltration
170[.]62[.]100[.]245Mullvad VPNAWS reconnaissance
185[.]77[.]218[.]4Oy Crea NovaTruffleHog secret validation
193[.]32[.]126[.]157Mullvad VPNGitHub exfiltration
209[.]159[.]147[.]239InterserverTruffleHog validation
23[.]234[.]107[.]104TzuloTruffleHog validation
34[.]205[.]27[.]48AmazonTruffleHog validation

Malicious File Hashes (SHA256)

Malicious Trivy Binaries (v0.69.4):

HashPlatform
887e1f5b5b50162a60bd03b66269e0ae545d0aef0583c1c5b00972152ad7e073FreeBSD-64bit
f7084b0229dce605ccc5506b14acd4d954a496da4b6134a294844ca8d601970dLinux-32bit
822dd269ec10459572dfaaefe163dae693c344249a0161953f0d5cdd110bd2a0Linux-64bit
bef7e2c5a92c4fa4af17791efc1e46311c0f304796f1172fce192f5efc40f5d7Linux-ARM
e64e152afe2c722d750f10259626f357cdea40420c5eedae37969fbf13abbecfLinux-ARM64
ecce7ae5ffc9f57bb70efd3ea136a2923f701334a8cd47d4fbf01a97fd22859cLinux-PPC64LE
d5edd791021b966fb6af0ace09319ace7b97d6642363ef27b3d5056ca654a94cLinux-s390x
e6310d8a003d7ac101a6b1cd39ff6c6a88ee454b767c1bdce143e04bc1113243macOS-64bit
6328a34b26a63423b555a61f89a6a0525a534e9c88584c815d937910f1ddd538macOS-ARM64
0880819ef821cff918960a39c1c1aada55a5593c61c608ea9215da858a86e349Windows-64bit

Additional Payload Hashes:

Hash
0c0d206d5e68c0cf64d57ffa8bc5b1dad54f2dda52f24e96e02e237498cb9c3a
0c6a3555c4eb49f240d7e0e3edbfbb3c900f123033b4f6e99ac3724b9b76278f
18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a
1e559c51f19972e96fcc5a92d710732159cdae72f407864607a513b20729decb
5e2ba7c4c53fa6e0cef58011acdd50682cf83fb7b989712d2fcf1b5173bad956
61ff00a81b19624adaad425b9129ba2f312f4ab76fb5ddc2c628a5037d31a4ba
7321caa303fe96ded0492c747d2f353c4f7d17185656fe292ab0a59e2bd0b8d9
7b5cc85e82249b0c452c66563edca498ce9d0c70badef04ab2c52acef4d629ca
7df6cef7ab9aae2ea08f2f872f6456b5d51d896ddda907a238cd6668ccdc4bb7
c37c0ae9641d2e5329fcdee847a756bf1140fdb7f0b7c78a40fdc39055e7d926
cd08115806662469bbedec4b03f8427b97c8a4b3bc1442dc18b72b4e19395fe3
e4edd126e139493d2721d50c3a8c49d3a23ad7766d0b90bc45979ba675f35fea
e87a55d3ba1c47e84207678b88cacb631a32d0cb3798610e7ef2d15307303c49
e9b1e069efc778c1e77fb3f5fcc3bd3580bbc810604cbf4347897ddb4b8c163b
f398f06eefcd3558c38820a397e3193856e4e6e7c67f81ecc8e533275284b152

Self-Signed Certificate Hashes (SHA256)

Hash
30015DD1E2CF4DBD49FFF9DDEF2AD4622DA2E60E5C0B6228595325532E948F14
41C4F2F37C0B257D1E20FE167F2098DA9D2E0A939B09ED3F63BC4FE010F8365C
D8CAF4581C9F0000C7568D78FB7D2E595AB36134E2346297D78615942CBBD727

Malicious Package Versions

PackageRegistryMalicious VersionsSafe Version
TrivyGitHub Releases / Docker Hubv0.69.4, v0.69.5, v0.69.6v0.69.3
trivy-actionGitHub Actions75 of 76 tags compromisedPin to verified SHA
setup-trivyGitHub ActionsAll 7 tagsPin to verified SHA
LiteLLMPyPIv1.82.7, v1.82.8v1.82.6
TelnyxPyPIv4.87.1, v4.87.2v4.87.0
checkmarx.ast-resultsOpen VSXv2.53Prior version
checkmarx.cx-dev-assistOpen VSXv1.7.0Prior version
47+ npm packagesnpmVariousAudit required

File Artifacts

FilenamePurpose
kamikaze.shInitial bash payload
kube.pyKubernetes lateral movement tool
prop.pyCredential harvester
proxy_server.pyStage 2 collector
tpcp.tar.gzEncrypted exfiltration archive
litellm_init.pthPython .pth auto-execution backdoor
hangup.wavWindows steganographic payload
ringtone.wavLinux steganographic payload
session.key / session.key.encEncryption key material
payload.encEncrypted payload
sysmon.service / sysmon.pySystemd persistence
pglog / .pg_stateMasqueraded PostgreSQL artifacts
msbuild.exeWindows persistence dropper
tpcp-docsFallback GitHub exfil repository

Behavioral Indicators

IndicatorContext
User-Agent: git/2.43.0Outdated git version used in post-compromise ops
User-Agent: Boto3/1.42.73 (Kali Linux)AWS operations from attacker infrastructure
Branch: dev_remote_ea5Eu/test/v1Nord Stream tool default branch name
GitHub repo: tpcp-docs or docs-tpcpFallback exfiltration dead-drop

MITRE ATT&CK Mapping

TacticIDTechniqueCampaign Context
Initial AccessT1195.001Supply Chain Compromise: Compromise Software Dependencies and Development ToolsPoisoned Trivy, KICS, LiteLLM, Telnyx packages
ExecutionT1059.004Command and Scripting Interpreter: Unix Shellkamikaze.sh bash payload
ExecutionT1059.006Command and Scripting Interpreter: Pythonkube.py, proxy_server.py, sysmon.py
ExecutionT1204.002User Execution: Malicious FilePackage installation triggers payload
PersistenceT1546.018Event Triggered Execution: .pth Filelitellm_init.pth auto-executes on Python startup
PersistenceT1543.002Create or Modify System Process: Systemd Servicesysmon.service for persistent C2 polling
PersistenceT1547.001Boot or Logon Autostart: Registry Run Keys / Startup Foldermsbuild.exe dropped to Windows Startup
Defense EvasionT1027Obfuscated Files or InformationBase64+zlib, RC4, WAV steganography
Defense EvasionT1036MasqueradingDisguised as systemd, PostgreSQL utilities
Defense EvasionT1562.001Impair Defenses: Disable or Modify ToolsGitHub secret masking bypass via /proc/pid/mem
Credential AccessT1552.001Unsecured Credentials: Credentials in Files50+ credential file paths targeted
Credential AccessT1552.005Unsecured Credentials: Cloud Instance Metadata APIIMDS token extraction (AWS/GCP/Azure)
Credential AccessT1528Steal Application Access TokenGitHub PATs, PyPI tokens, K8s service account tokens
DiscoveryT1526Cloud Service DiscoveryAWS ListUsers, DescribeInstances, ListClusters, ListSecrets
DiscoveryT1613Container and Resource DiscoveryK8s API enumeration, Docker API scanning
Lateral MovementT1021.007Remote Services: Cloud ServicesECS Exec, K8s DaemonSet deployment
Lateral MovementT1550.001Use Alternate Authentication Material: Application Access TokenStolen GitHub PATs for cross-repo access
CollectionT1005Data from Local SystemSSH keys, cloud creds, K8s secrets, .env files
ExfiltrationT1041Exfiltration Over C2 ChannelAES-256-CBC + RSA-4096 encrypted bundles to C2
ExfiltrationT1537Transfer Data to Cloud AccountS3 bucket access, GitHub repo dead-drops
ImpactT1561Disk WipeCanisterWorm wiper component (March 23, Iran)
ImpactT1531Account Access RemovalRecursive file deletion on non-containerized hosts

Affected Organizations & Impact

  • European Commission: 92 GB exfiltrated from AWS infrastructure (42 internal clients, 29 EU entities); data appeared on ShinyHunters' site
  • Mandiant estimate: 1,000+ SaaS environments impacted, projected to reach 5,000–10,000
  • Unit 42 telemetry: 300 GB+ data from 500,000+ machines; 16+ organizations publicly leaked
  • AstraZeneca: Named as victim by LAPSUS$ (unconfirmed) — claimed 3 GB including code repos, AWS/Azure configs, Terraform, GitHub Enterprise
  • Vect RaaS partnership: ~300,000 BreachForums affiliates received individual ransomware keys

CVE Details

CVE-2026-33634 — Remote Supply Chain Compromise in Trivy Ecosystem via Non-Atomic Secret Rotation

  • CVSS v4.0: 9.4 (CRITICAL)
  • CVSS v3.1: 8.8 (HIGH)
  • CWE: CWE-506 (Embedded Malicious Code)
  • CISA KEV Deadline: April 8, 2026

CVE-2026-33017 — Langflow Unauthenticated RCE (related; versions prior to 1.8.2)

  • CISA KEV Deadline: April 9, 2026

Detection Rules

The following detection rules target TeamPCP's core TTPs: supply chain payload execution, credential harvesting from CI/CD runners and cloud metadata services, persistence via .pth files and systemd services, WAV steganography payload delivery, and C2 communication. Rules cover process execution logs, file system events, network traffic, and file-level indicators. Log sources include Sysmon (Linux/Windows), cloud audit logs, DNS logs, and network flow data. All Sigma rules validated with sigma check (exit 0). All YARA rules validated with yarac (exit 0). Snort/Suricata rules are syntactically correct but Snort was not available for runtime validation.

Sigma Rules

1. TeamPCP Cloud Stealer — Proc Memory Scraping for GitHub Secrets

yaml
title: TeamPCP Proc Memory Scraping for CI/CD Secrets
id: 7a3b9c01-d4e5-4f6a-8b7c-9d0e1f2a3b4c
status: experimental
description: >
    Detects access to /proc/pid/mem files commonly used by TeamPCP Cloud Stealer
    to bypass GitHub Actions secret masking and extract CI/CD credentials.
references:
    - https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/
    - https://www.wiz.io/blog/trivy-compromised-teampcp-supply-chain-attack
author: Actioner Research
date: 2026-04-07
tags:
    - attack.credential_access
    - attack.t1003
    - attack.t1552.001
logsource:
    product: linux
    category: file_access
detection:
    selection:
        TargetFilename|re: '/proc/\d+/mem'
    filter_known:
        Image|endswith:
            - '/gdb'
            - '/strace'
            - '/lldb'
            - '/valgrind'
    condition: selection and not filter_known
falsepositives:
    - Legitimate debugging tools
    - Memory profiling applications
level: high

2. TeamPCP Persistence — Malicious .pth File Creation

yaml
title: TeamPCP Malicious Python .pth File in Site-Packages
id: 8b4c0d12-e5f6-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: >
    Detects creation of .pth files in Python site-packages directories, a technique
    used by TeamPCP's LiteLLM payload for auto-execution on every Python process start.
references:
    - https://isc.sans.edu/diary/32838
    - https://www.reversinglabs.com/blog/teampcp-supply-chain-attack-spreads
author: Actioner Research
date: 2026-04-07
tags:
    - attack.persistence
    - attack.t1546
logsource:
    product: linux
    category: file_event
detection:
    selection:
        TargetFilename|contains: 'site-packages/'
        TargetFilename|endswith: '.pth'
    filter_pip:
        Image|endswith:
            - '/pip'
            - '/pip3'
            - '/python'
            - '/python3'
        CommandLine|contains:
            - 'install'
            - 'setup.py'
    condition: selection and not filter_pip
falsepositives:
    - Legitimate Python package installations
    - Development environment setup
level: high

3. TeamPCP Persistence — Systemd User Service Masquerading as Sysmon

yaml
title: TeamPCP Systemd Persistence via Fake Sysmon Service
id: 9c5d1e23-f6a7-4b8c-0d9e-1f2a3b4c5d6e
status: experimental
description: >
    Detects creation of systemd user service files that masquerade as sysmon or
    PostgreSQL monitoring, consistent with TeamPCP Cloud Stealer persistence.
references:
    - https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/
    - https://ramimac.me/teampcp/
author: Actioner Research
date: 2026-04-07
tags:
    - attack.persistence
    - attack.t1543.002
    - attack.t1036
logsource:
    product: linux
    category: file_event
detection:
    selection_sysmon:
        TargetFilename|contains: '.config/systemd/user/'
        TargetFilename|endswith:
            - 'sysmon.service'
            - 'sysmon.py'
    selection_pgmon:
        TargetFilename|contains: '.config/systemd/user/'
        TargetFilename|endswith:
            - 'pgmon.service'
            - 'pglog'
    condition: selection_sysmon or selection_pgmon
falsepositives:
    - Legitimate sysmon for Linux installations (rare in user systemd directory)
level: critical

4. TeamPCP C2 — DNS Queries to Known Infrastructure

yaml
title: TeamPCP C2 Domain DNS Resolution
id: 0d6e2f34-a7b8-4c9d-1e0f-2a3b4c5d6e7f
status: experimental
description: >
    Detects DNS queries to known TeamPCP command and control domains including
    typosquatted security vendor domains and ICP-hosted fallback infrastructure.
references:
    - https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/
    - https://www.wiz.io/blog/trivy-compromised-teampcp-supply-chain-attack
author: Actioner Research
date: 2026-04-07
tags:
    - attack.command_and_control
    - attack.t1071.001
logsource:
    category: dns
detection:
    selection:
        query|endswith:
            - 'aquasecurtiy.org'
            - 'checkmarx.zone'
            - 'litellm.cloud'
            - 'nsa.cat'
            - 'icp0.io'
    condition: selection
falsepositives:
    - Unlikely
level: critical

5. TeamPCP Credential Harvesting — IMDS Access from Python Process

yaml
title: TeamPCP Cloud Metadata Service Access from Python
id: 1e7f3a45-b8c9-4d0e-2f1a-3b4c5d6e7f8a
status: experimental
description: >
    Detects Python processes accessing cloud instance metadata services (IMDS),
    a key TTP in TeamPCP's credential harvesting from CI/CD and cloud environments.
references:
    - https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/
    - https://www.wiz.io/blog/tracking-teampcp-investigating-post-compromise-attacks-seen-in-the-wild
author: Actioner Research
date: 2026-04-07
tags:
    - attack.credential_access
    - attack.t1552.005
logsource:
    category: proxy
detection:
    selection_process:
        c-useragent|contains: 'python'
    selection_imds:
        r-dns:
            - '169.254.169.254'
            - 'metadata.google.internal'
    condition: selection_process and selection_imds
falsepositives:
    - Legitimate cloud SDKs running in Python
    - Cloud-aware applications querying instance metadata
level: medium

6. TeamPCP Exfiltration — GitHub Dead-Drop Repository Creation

yaml
title: TeamPCP GitHub Dead-Drop Repository Creation
id: 2f8a4b56-c9d0-4e1f-3a2b-4c5d6e7f8a9b
status: experimental
description: >
    Detects creation of GitHub repositories named tpcp-docs or docs-tpcp,
    used by TeamPCP as fallback exfiltration dead-drops for stolen credentials.
references:
    - https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/
    - https://www.wiz.io/blog/trivy-compromised-teampcp-supply-chain-attack
author: Actioner Research
date: 2026-04-07
tags:
    - attack.exfiltration
    - attack.t1537
logsource:
    product: github
    service: audit
detection:
    selection:
        action: 'repo.create'
        repo|contains:
            - 'tpcp-docs'
            - 'docs-tpcp'
    condition: selection
falsepositives:
    - Unlikely
level: critical

7. TeamPCP Post-Compromise — AWS Bulk Enumeration from Known IPs

yaml
title: TeamPCP AWS Bulk Enumeration from Known IPs
id: 3a9b5c67-d0e1-4f2a-4b3c-5d6e7f8a9b0c
status: experimental
description: >
    Detects bulk AWS API enumeration calls originating from known TeamPCP
    operational IP addresses used for post-compromise reconnaissance.
references:
    - https://www.wiz.io/blog/tracking-teampcp-investigating-post-compromise-attacks-seen-in-the-wild
author: Actioner Research
date: 2026-04-07
tags:
    - attack.discovery
    - attack.t1526
logsource:
    product: aws
    service: cloudtrail
detection:
    selection_api:
        eventName:
            - 'ListUsers'
            - 'ListRoles'
            - 'ListAttachedUserPolicies'
            - 'DescribeInstances'
            - 'ListSecrets'
            - 'GetSecretValue'
            - 'ListBuckets'
            - 'ListClusters'
            - 'ListFunctions'
    selection_ip:
        sourceIPAddress:
            - '138.199.15.172'
            - '154.47.29.12'
            - '170.62.100.245'
            - '193.32.126.157'
            - '163.245.223.12'
            - '209.159.147.239'
    condition: selection_api and selection_ip
falsepositives:
    - Legitimate automation from these IPs (unlikely)
level: critical

YARA Rules

1. TeamPCP Cloud Stealer — Credential Harvester

yara
rule TeamPCP_CloudStealer_CredentialHarvester
{
    meta:
        description = "Detects TeamPCP Cloud Stealer credential harvesting payloads targeting CI/CD secrets and cloud credentials"
        author = "Actioner Research"
        date = "2026-04-07"
        reference = "https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/"
        severity = "critical"

    strings:
        $exfil_archive = "tpcp.tar.gz" ascii wide
        $exfil_repo1 = "tpcp-docs" ascii wide
        $exfil_repo2 = "docs-tpcp" ascii wide
        $c2_aqua = "aquasecurtiy" ascii wide
        $c2_checkmarx = "checkmarx.zone" ascii wide
        $c2_litellm = "models.litellm.cloud" ascii wide
        $secret_pattern = "{\"value\":\"" ascii
        $secret_isSecret = "\"isSecret\":true}" ascii
        $proc_mem = "/proc/" ascii
        $session_key = "session.key" ascii
        $payload_enc = "payload.enc" ascii
        $sysmon_path = ".config/systemd/user/sysmon" ascii
        $kamikaze = "kamikaze.sh" ascii
        $pglog = "/tmp/pglog" ascii

    condition:
        uint8(0) != 0x4d and
        (
            ($exfil_archive and any of ($c2_*)) or
            ($secret_pattern and $secret_isSecret and $proc_mem) or
            (3 of ($c2_aqua, $c2_checkmarx, $c2_litellm, $exfil_repo1, $exfil_repo2)) or
            ($sysmon_path and $pglog) or
            ($kamikaze and any of ($c2_*)) or
            ($session_key and $payload_enc and $exfil_archive)
        )
}

2. TeamPCP WAV Steganography Payload

yara
rule TeamPCP_WAV_Steganography_Payload
{
    meta:
        description = "Detects WAV files containing TeamPCP steganographic payloads used in the Telnyx supply chain compromise"
        author = "Actioner Research"
        date = "2026-04-07"
        reference = "https://isc.sans.edu/diary/32838"
        severity = "critical"

    strings:
        $wav_header = { 52 49 46 46 ?? ?? ?? ?? 57 41 56 45 }
        $msbuild = "msbuild.exe" ascii wide
        $tpcp_tar = "tpcp.tar.gz" ascii wide
        $session_key = "session.key" ascii wide
        $rsa_begin = "-----BEGIN PUBLIC KEY-----" ascii
        $aes_cbc = "AES-256-CBC" ascii wide

    condition:
        $wav_header at 0 and
        (
            $msbuild or
            $tpcp_tar or
            ($session_key and $rsa_begin) or
            ($aes_cbc and ($tpcp_tar or $session_key))
        )
}

3. TeamPCP LiteLLM Malicious .pth Backdoor

yara
rule TeamPCP_LiteLLM_Pth_Backdoor
{
    meta:
        description = "Detects the malicious .pth file used in the LiteLLM supply chain compromise for Python auto-execution persistence"
        author = "Actioner Research"
        date = "2026-04-07"
        reference = "https://ramimac.me/teampcp/"
        severity = "critical"

    strings:
        $pth_import = "import " ascii
        $litellm_init = "litellm_init" ascii
        $icp_c2 = "icp0.io" ascii
        $sysmon_py = "sysmon.py" ascii
        $proxy_server = "proxy_server.py" ascii
        $base64_zlib1 = "base64" ascii
        $base64_zlib2 = "zlib" ascii
        $rc4_ref = "RC4" ascii nocase

    condition:
        filesize < 100KB and
        $pth_import and
        (
            ($litellm_init and ($icp_c2 or $sysmon_py)) or
            ($proxy_server and $sysmon_py) or
            ($base64_zlib1 and $base64_zlib2 and ($icp_c2 or $sysmon_py)) or
            ($rc4_ref and ($icp_c2 or $litellm_init))
        )
}

Suricata Rules

# TeamPCP C2 Communication - Typosquatted Aqua Security Domain
alert tls $HOME_NET any -> $EXTERNAL_NET any (msg:"ETPRO TROJAN TeamPCP C2 - scan.aquasecurtiy.org TLS SNI"; flow:established,to_server; tls.sni; content:"scan.aquasecurtiy.org"; nocase; classtype:trojan-activity; sid:2026001; rev:1;)

# TeamPCP C2 Communication - checkmarx.zone
alert tls $HOME_NET any -> $EXTERNAL_NET any (msg:"ETPRO TROJAN TeamPCP C2 - checkmarx.zone TLS SNI"; flow:established,to_server; tls.sni; content:"checkmarx.zone"; nocase; classtype:trojan-activity; sid:2026002; rev:1;)

# TeamPCP C2 Communication - models.litellm.cloud
alert tls $HOME_NET any -> $EXTERNAL_NET any (msg:"ETPRO TROJAN TeamPCP C2 - models.litellm.cloud TLS SNI"; flow:established,to_server; tls.sni; content:"models.litellm.cloud"; nocase; classtype:trojan-activity; sid:2026003; rev:1;)

# TeamPCP C2 Communication - ICP Fallback
alert tls $HOME_NET any -> $EXTERNAL_NET any (msg:"ETPRO TROJAN TeamPCP ICP Fallback C2"; flow:established,to_server; tls.sni; content:"icp0.io"; nocase; classtype:trojan-activity; sid:2026004; rev:1;)

# TeamPCP C2 Communication - nsa.cat
alert tls $HOME_NET any -> $EXTERNAL_NET any (msg:"ETPRO TROJAN TeamPCP C2 - nsa.cat TLS SNI"; flow:established,to_server; tls.sni; content:"nsa.cat"; nocase; classtype:trojan-activity; sid:2026005; rev:1;)

# TeamPCP Exfiltration Archive Pattern
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ETPRO TROJAN TeamPCP Exfil Archive Upload (tpcp.tar.gz)"; flow:established,to_server; http.method; content:"POST"; http.content_type; content:"application/"; http.request_body; content:"tpcp.tar.gz"; classtype:trojan-activity; sid:2026006; rev:1;)

# TeamPCP Known C2 IP (45.148.10.212)
alert ip $HOME_NET any -> 45.148.10.212 any (msg:"ETPRO TROJAN TeamPCP Known C2 IP (45.148.10.212)"; classtype:trojan-activity; sid:2026007; rev:1;)

# TeamPCP Known C2 IP (83.142.209.203)
alert ip $HOME_NET any -> 83.142.209.203 any (msg:"ETPRO TROJAN TeamPCP Known C2 IP (83.142.209.203)"; classtype:trojan-activity; sid:2026008; rev:1;)

Remediation Guidance

Immediate Actions

  1. Audit CI/CD pipelines for any use of compromised package versions (Trivy v0.69.4–v0.69.6, LiteLLM v1.82.7–v1.82.8, Telnyx v4.87.1–v4.87.2, KICS compromised tags)
  2. Rotate ALL credentials that may have been exposed: GitHub PATs, AWS keys, SSH keys, K8s service account tokens, PyPI tokens, .env file contents
  3. Search for fallback repositories named tpcp-docs or docs-tpcp in all organizational GitHub accounts
  4. Scan for persistence artifacts: ~/.config/systemd/user/sysmon.py, sysmon.service, /tmp/pglog, .pg_state
  5. Block C2 infrastructure at network level: all domains and IPs listed in IOC section
  6. Check for malicious .pth files in Python site-packages directories

Hardening

  1. Pin GitHub Actions to full commit SHA hashes — never use version tags (this attack proves tags can be hijacked)
  2. Pin package versions explicitly — disable auto-update in CI/CD
  3. Implement SLSA framework for supply chain integrity verification
  4. Enable branch protection with required reviews for all tag/release operations
  5. Use OIDC-based authentication instead of long-lived PATs in CI/CD
  6. Disable automounting of K8s service account tokens where not needed
  7. Monitor IMDS access from unexpected processes; consider IMDSv2 enforcement on AWS

Sources

MIT License