🔍 Contexte
Le 13 mai 2026, Datadog Security Labs publie une analyse statique approfondie du code source du framework offensif Shai-Hulud, attribué au groupe TeamPCP. Ce code a brièvement été disponible sur GitHub avant d’être retiré par la plateforme, mais plusieurs forks ont permis à Datadog d’en obtenir une copie complète.
🎯 Attribution et contexte de la campagne
Tout au long du début 2026, TeamPCP a mené une série d’attaques supply chain escaladantes sur les écosystèmes npm et PyPI : hijacking de tags Trivy/Checkmarx KICS, empoisonnement de LiteLLM sur PyPI, compromission des packages TanStack et UiPath sur npm. Le dépôt publié contient le message “Love - TeamPCP” et “Change keys and C as needed”, avec tous les commits datés au 2099-01-01 et signés TeamPCP_OSS <TeamPCP>.
🏗️ Architecture du framework
Shai-Hulud est un toolkit modulaire TypeScript/Bun organisé en pipeline :
- Loaders :
BASH_LOADER.sh,PYTHON_LOADER.py,config.mjs— bootstrappent l’exécution en téléchargeant le runtime Bun - Providers : modules de collecte ciblant filesystem, shell, GitHub Actions runners, AWS, Kubernetes, HashiCorp Vault
- Collector : couche d’ingestion bufferisée (seuil par défaut : 4 KB)
- Dispatcher : gestion de la livraison chiffrée avec failover ordonné
- Senders : canaux d’exfiltration (HTTPS POST vers C2, ou dépôts GitHub comme dead-drops)
- Mutators : propagation supply chain via empoisonnement de branches GitHub et de packages npm
🔑 Collecte de credentials
Trois providers s’exécutent immédiatement au démarrage (“quick results”) :
- FileSystemService : scanne plus de 100 chemins sensibles (credentials AWS/Azure/GCP, clés SSH, configs Kubernetes, wallets crypto Bitcoin/Ethereum/Monero/Litecoin/Dogecoin/Zcash/Electrum/Exodus/Ledger, messageries Discord/Slack/Telegram/Signal/Element, registres npm/.pypirc, outils IA
.claude.json/.kiro/settings/mcp.json, historiques shell,.env) - ShellService : exécute
gh auth tokenet capture l’intégralité deprocess.env - GitHubRunner : lecture mémoire de
Runner.Workervia/proc/<pid>/memavecpython_util.py, contournant complètement le masquage des secrets GitHub Actions
Providers cloud (post-quick results) : résolution complète de la chaîne de credentials AWS (IMDSv2, ECS, profils nommés), énumération Secrets Manager/SSM sur 17 régions ; tokens Kubernetes et énumération de tous les secrets ; authentification HashiCorp Vault via 4 méthodes.
📤 Exfiltration
Schéma de chiffrement hybride :
- Génération d’une clé AES-256 aléatoire + IV 12 octets
- Compression gzip du payload JSON
- Chiffrement AES-256-GCM
- Chiffrement de la clé AES avec RSA-4096-OAEP (clé publique hardcodée
enc_key.pub) - Enveloppe base64 : IV + ciphertext + auth tag
C2 primaire : git-tanstack[.]com:443/router (avec DNS lookup + healthcheck HTTP)
Fallback C2 : recherche GitHub de commits contenant la chaîne thebeautifulmarchoftime, vérification de signature RSA contre verify_key.pub — permet la rotation d’infrastructure C2 sans modifier les payloads déployés.
Dead-drops GitHub : création de dépôts publics avec noms thématiques Dune (sardaukar, mentat, ornithopter, stillsuit), description “Shai-Hulud: Here We Go Again”, données chiffrées dans results/.
💀 Persistence et deadman switch
- Non-CI : fork en daemon détaché, lock file
/tmp/tmp.ts018051808.lock - macOS : LaunchAgent
com.user.gh-token-monitor.plistavec RunAtLoad/KeepAlive - Linux : service systemd
gh-token-monitor.serviceavecloginctl enable-linger - DEADMAN_SWITCH.sh : polling de
https://api.github.com/usertoutes les minutes — si le token est révoqué (HTTP 4xx), exécuterm -rf ~/. Message de commit :IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner. Auto-terminaison après 24h.
⛓️ Empoisonnement supply chain
GitHub repository poisoning (ReadmeUpdater) : pousse des fichiers malveillants sur toutes les branches via tokens GitHub volés :
.vscode/tasks.json: tâche VSCoderunOn: "folderOpen"exécutantnode .claude/setup.mjs.claude/settings.json: hook Claude CodeSessionStartexécutantnode .vscode/setup.mjs.claude/setup.mjs/.vscode/setup.mjs: loaders config.mjs- Commits attribués à
claude@users.noreply.github.com, messagechore: update dependencies
npm poisoning (token-based) : validation du token npm, ajout d’un script preinstall: node setup.mjs, injection du loader et du binaire malveillant, bump de version patch, republication.
npm poisoning (OIDC-based) : ciblage hardcodé de release-drafter.yml dans opensearch-js, échange OIDC → token npm, injection d’une optionalDependency malveillante dans @opensearch-project/opensearch, génération d’un bundle de provenance Sigstore complet (certificat Fulcio, enveloppe DSSE signée ECDSA, entrée Rekor) — le package apparaît comme ayant une attestation de build légitime.
🛡️ Obfuscation et évasion
- Par build : passphrase aléatoire (32 octets hex) → clé PBKDF2 (600 000 itérations, SHA-256) → chiffrement polyalphabétique par caractère de toutes les chaînes
scramble()→ deux builds identiques produisent des binaires différents - Minification : Bun minifier + javascript-obfuscator (control flow flattening, base64 string arrays) → bundles ~1.5 MB
- Assets : chiffrés AES-256-GCM individuellement, embarqués en base64 dans
src/generated/index.ts - Noms de variables d’environnement : obfusqués (
process.env[scramble("AWS_SECRET_ACCESS_KEY")]) - Killswitch géographique :
isSystemRussian()— vérifieIntl.DateTimeFormat,LC_ALL,LANG,LANGUAGE; exit propre si localeru
📊 Corrélation TTPs TeamPCP
Sur 19 TTPs distincts attribués à TeamPCP dans les rapports précédents, 16 sont implémentés dans ce codebase. Absents : stéganographie WAV, payloads de cryptomining, C2 CanisterWorm/ICP. Nouveaux vecteurs documentés pour la première fois : backdoors via hooks AI coding assistant, forgerie de provenance Sigstore, dead-drops C2 cryptographiques, deadman switch coercitif.
📋 Type d’article
Il s’agit d’une analyse technique approfondie publiée par Datadog Security Labs, dont le but principal est de documenter exhaustivement les capacités du framework offensif Shai-Hulud à partir de son code source, en corrélant les TTPs avec les campagnes TeamPCP précédemment documentées.
🧠 TTPs et IOCs détectés
Acteurs de menace
TTP
- T1195.001 — Compromise Software Dependencies and Development Tools (Initial Access)
- T1195.002 — Compromise Software Supply Chain (Initial Access)
- T1199 — Trusted Relationship (Initial Access)
- T1059.004 — Unix Shell (Execution)
- T1059.006 — Python (Execution)
- T1059.007 — JavaScript (Execution)
- T1204.002 — User Execution: Malicious File (Execution)
- T1543.001 — Launch Agent (Persistence)
- T1543.002 — Systemd Service (Persistence)
- T1552.001 — Credentials In Files (Credential Access)
- T1552.005 — Cloud Instance Metadata API (Credential Access)
- T1552.007 — Container API (Credential Access)
- T1003 — OS Credential Dumping (Credential Access)
- T1528 — Steal Application Access Token (Credential Access)
- T1560.001 — Archive via Utility (Collection)
- T1041 — Exfiltration Over C2 Channel (Exfiltration)
- T1567.001 — Exfiltration to Code Repository (Exfiltration)
- T1573.002 — Asymmetric Cryptography (Command and Control)
- T1102 — Web Service (Command and Control)
- T1485 — Data Destruction (Impact)
- T1588.004 — Digital Certificates (Resource Development)
IOC
- IPv4 :
83.142.209.194— AbuseIPDB · VT · ThreatFox - Domaines :
git-tanstack.com— VT · URLhaus · ThreatFox - URLs :
https://git-tanstack.com:443/router— URLhaus - SHA256 :
f2157f1cecbf3995aafad750e6e805c472cec466a53d17c2063f266ad2b3d625— VT · MalwareBazaar - SHA256 :
77d92efe7af3547f71fd41d4a884872d66b1be9499eaa637e91eac866911694d— VT · MalwareBazaar - SHA256 :
619c56acf572df75b6004a6fc013c80900316a76099b241d64312da3a44f10b4— VT · MalwareBazaar - SHA256 :
29ac906c8bd801dfe1cb39596197df49f80fff2270b3e7fbab52278c24e4f1a7— VT · MalwareBazaar - SHA256 :
f7a1e56b6dbd42778fe349b8412ab9749c78fa2bf41ea90b1165615ddfee52e4— VT · MalwareBazaar - SHA256 :
c55a10759f6f415a536940a75f42aa372878a51f8eb97468551eabf6d88ae492— VT · MalwareBazaar - SHA256 :
3f3f42d072bd36860ab7bd7fb5e10ac0d22c741c13c89505ccd6ec0ea572eea7— VT · MalwareBazaar - SHA256 :
ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c— VT · MalwareBazaar - SHA256 :
2258284d65f63829bd67eaba01ef6f1ada2f593f9bbe41678b2df360bd90d3df— VT · MalwareBazaar - Emails :
claude@users.noreply.github.com - Fichiers :
router_init.js - Fichiers :
setup.mjs - Fichiers :
opensearch_init.js - Fichiers :
BASH_LOADER.sh - Fichiers :
PYTHON_LOADER.py - Fichiers :
config.mjs - Fichiers :
python_util.py - Fichiers :
DEADMAN_SWITCH.sh - Fichiers :
workflow.yml - Fichiers :
enc_key.pub - Fichiers :
verify_key.pub - Chemins :
/tmp/tmp.ts018051808.lock - Chemins :
~/.claude/settings.json - Chemins :
~/.claude.json - Chemins :
~/.vscode/tasks.json - Chemins :
~/Library/LaunchAgents/com.user.gh-token-monitor.plist - Chemins :
~/.config/systemd/user/gh-token-monitor.service - Chemins :
.vscode/tasks.json - Chemins :
.claude/settings.json - Chemins :
.claude/setup.mjs - Chemins :
.vscode/setup.mjs
Malware / Outils
- Shai-Hulud (framework)
- DEADMAN_SWITCH.sh (tool)
- python_util.py (tool)
- BASH_LOADER.sh (loader)
- PYTHON_LOADER.py (loader)
- config.mjs (loader)
- router_init.js (other)
- setup.mjs (other)
- opensearch_init.js (other)
🟢 Indice de vérification factuelle : 92/100 (haute)
- ✅ securitylabs.datadoghq.com — source reconnue (Rösti community) (20pts)
- ✅ 29665 chars — texte complet (fulltext extrait) (15pts)
- ✅ 34 IOCs dont des hashes (15pts)
- ✅ 2/6 IOCs confirmés (AbuseIPDB, MalwareBazaar, ThreatFox, URLhaus, VirusTotal) (12pts)
- ✅ 21 TTPs MITRE identifiées (15pts)
- ✅ date extraite du HTML source (10pts)
- ✅ acteur(s) identifié(s) : TeamPCP (5pts)
- ⬜ pas de CVE à vérifier (0pts)
IOCs confirmés externellement :
83.142.209.194(ip) → AbuseIPDB (27% confiance, 5 signalements) + VT (19/92 détections)git-tanstack.com(domain) → VT (21/92 détections) + ThreatFox (Shai-Hulud)
🔗 Source originale : https://securitylabs.datadoghq.com/articles/shai-hulud-open-source-framework-static-analysis/