🔍 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 token et capture l’intégralité de process.env
  • GitHubRunner : lecture mémoire de Runner.Worker via /proc/<pid>/mem avec python_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 :

  1. Génération d’une clé AES-256 aléatoire + IV 12 octets
  2. Compression gzip du payload JSON
  3. Chiffrement AES-256-GCM
  4. Chiffrement de la clé AES avec RSA-4096-OAEP (clé publique hardcodée enc_key.pub)
  5. 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.plist avec RunAtLoad/KeepAlive
  • Linux : service systemd gh-token-monitor.service avec loginctl enable-linger
  • DEADMAN_SWITCH.sh : polling de https://api.github.com/user toutes les minutes — si le token est révoqué (HTTP 4xx), exécute rm -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 VSCode runOn: "folderOpen" exécutant node .claude/setup.mjs
  • .claude/settings.json : hook Claude Code SessionStart exécutant node .vscode/setup.mjs
  • .claude/setup.mjs / .vscode/setup.mjs : loaders config.mjs
  • Commits attribués à claude@users.noreply.github.com, message chore: 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érifie Intl.DateTimeFormat, LC_ALL, LANG, LANGUAGE ; exit propre si locale ru

📊 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.194AbuseIPDB · VT · ThreatFox
  • Domaines : git-tanstack.comVT · URLhaus · ThreatFox
  • URLs : https://git-tanstack.com:443/routerURLhaus
  • SHA256 : f2157f1cecbf3995aafad750e6e805c472cec466a53d17c2063f266ad2b3d625VT · MalwareBazaar
  • SHA256 : 77d92efe7af3547f71fd41d4a884872d66b1be9499eaa637e91eac866911694dVT · MalwareBazaar
  • SHA256 : 619c56acf572df75b6004a6fc013c80900316a76099b241d64312da3a44f10b4VT · MalwareBazaar
  • SHA256 : 29ac906c8bd801dfe1cb39596197df49f80fff2270b3e7fbab52278c24e4f1a7VT · MalwareBazaar
  • SHA256 : f7a1e56b6dbd42778fe349b8412ab9749c78fa2bf41ea90b1165615ddfee52e4VT · MalwareBazaar
  • SHA256 : c55a10759f6f415a536940a75f42aa372878a51f8eb97468551eabf6d88ae492VT · MalwareBazaar
  • SHA256 : 3f3f42d072bd36860ab7bd7fb5e10ac0d22c741c13c89505ccd6ec0ea572eea7VT · MalwareBazaar
  • SHA256 : ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266cVT · MalwareBazaar
  • SHA256 : 2258284d65f63829bd67eaba01ef6f1ada2f593f9bbe41678b2df360bd90d3dfVT · 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/