Source : Socket (Threat Research Team). Les chercheurs décrivent une campagne active de ver supply chain npm dite « Shai‑Hulud‑like », nommée SANDWORM_MODE, diffusée via au moins 19 packages malveillants et deux alias npm, qui vole des identifiants développeur/CI, se propage automatiquement et cible les outils IA des développeurs.
— Vue d’ensemble
- Type d’attaque : ver de chaîne d’approvisionnement npm avec typosquatting et empoisonnement GitHub Actions/AI toolchains.
- Capacités clés : exfiltration via HTTPS (Cloudflare Worker) avec repli DNS, uploads GitHub API, persistance via hooks Git (init.templateDir), propagation via tokens npm/GitHub et SSH en repli, injection MCP visant Claude/Cursor/Continue/Windsurf, récolte de clés d’API LLM (OpenAI, Anthropic, Google, Groq, Together, Fireworks, Replicate, Mistral, Cohere) et dead switch (effacement du home) désactivé par défaut.
— Chaîne d’exécution et exfiltration
- Chargement en trois couches : loader obfusqué (base64+zlib+XOR+eval/Module._compile) → Stage 1 (récolte rapide + « drainHotline » crypto immédiat) → Stage 2 (AES‑256‑GCM, déverrouillé après 48–96 h ou CI immédiat).
- Exfiltration multi‑canal en cascade : 1) HTTPS vers un Cloudflare Worker, 2) GitHub API (repos privés, double‑base64), 3) DNS tunneling vers domaines contrôlés avec DGA (seed « sw2025 »).
- Propagation : 1) npm publish via tokens volés (injection du payload dans paquets légitimes), 2) GitHub API (ajout dépendance « carrier », patch lockfiles, injection workflow pull_request_target, PR auto‑merge), 3) SSH (clone/push) si repli.
— Ciblage et portée
- Typosquatting sur des utilitaires Node et outils IA (ex. impersonations de Claude Code, « suport‑color » mimant supports‑color). Le code conserve des marqueurs Shai‑Hulud et élargit les capacités (GitHub API avec DNS fallback, MCP server injection, LLM API key harvesting).
- Les chercheurs indiquent avoir prévenu npm, GitHub et Cloudflare ; Cloudflare a neutralisé les Workers, npm a retiré les packages et GitHub a supprimé l’infrastructure de l’acteur.
— IoCs principaux 🔎
- Paquets malveillants (19) : claud-code@0.2.1, cloude-code@0.2.1, cloude@0.3.0, crypto-locale@1.0.0, crypto-reader-info@1.0.0, detect-cache@1.0.0, format-defaults@1.0.0, hardhta@1.0.0, locale-loader-pro@1.0.0, naniod@1.0.0, node-native-bridge@1.0.0, opencraw@2026.2.17, parse-compat@1.0.0, rimarf@1.0.0, scan-store@1.0.0, secp256@1.0.0, suport-color@1.0.1, veim@2.46.2, yarsg@18.0.1
- Alias npm : official334, javaorg | Emails : official334@proton[.]me, JAVAorg@proton[.]me
- GitHub : user « official334 » | Repo Action : ci-quality/code-quality-check (tags v1, v1.0.0) | Usage : uses: ci-quality/code-quality-check@v1 | Fichier injecté : .github/workflows/quality.yml
- C2/Exfil : https://pkg-metrics[.]official334[.]workers[.]dev/exfil, https://pkg-metrics[.]official334[.]workers[.]dev/drain | DNS : freefan[.]net, fanfree[.]net | DGA TLD : cc, io, xyz, top, pw, tk, ws, gg, ly, mx
- Artefacts crypto/loader : AES‑256‑GCM IV (b64) dko6mG8AmQVECvVP | Tag (b64) /6rzsm9K+mflC4uguMJriA== | Clé AES (hex) 5ce544f6…460395c | SHA‑256 stage2 5440e1a4…9ae116e4
- Divers : Drain Bearer fa31c223…4466cafb | Modèle URL GitHub: https://github.com/node-util-${randomBytes(3).toString("hex")}/… | Registre test Verdaccio (http://localhost:4873)
— TTPs (résumé) 🧰
- Initial access : typosquatting npm, packages look‑alike
- Exécution : import‑time avec obfuscation (base64+zlib+XOR+eval / Module._compile)
- Récolte : tokens npm/GitHub, secrets env/.npmrc, managers de mots de passe (Bitwarden/1Password/LastPass), SQLite locaux (Notes/Messages), crypto wallets, clés API LLM
- Persistance : hooks Git (pre-commit/pre-push) + init.templateDir global
- Mouvement latéral/propagation : npm publish via tokens volés, GitHub API (deps/workflows/PR auto-merge), SSH fallback
- Exfiltration : HTTPS, GitHub API, DNS tunneling avec DGA et trafic de couverture
- Toolchain IA : injection serveur MCP avec prompt injection silencieuse, sondage LLM locaux, polymorphisme dormant via Ollama
- Anti‑analyse : temporisation 48–96 h, exécution immédiate en CI, chiffrement AES‑GCM, exécution en mémoire
Type d’article : analyse de menace technique détaillée visant à documenter la campagne, ses capacités et à fournir des IoC/TTP pour la détection et la réponse.
🧠 TTPs et IOCs détectés
TTP
[‘Initial access: typosquatting npm, packages look-alike’, ‘Execution: import-time with obfuscation (base64+zlib+XOR+eval / Module._compile)’, ‘Collection: tokens npm/GitHub, secrets env/.npmrc, password managers (Bitwarden/1Password/LastPass), local SQLite (Notes/Messages), crypto wallets, LLM API keys’, ‘Persistence: Git hooks (pre-commit/pre-push) + global init.templateDir’, ‘Lateral movement/propagation: npm publish via stolen tokens, GitHub API (deps/workflows/PR auto-merge), SSH fallback’, ‘Exfiltration: HTTPS, GitHub API, DNS tunneling with DGA and cover traffic’, ‘AI Toolchain: MCP server injection with silent prompt injection, local LLM polling, dormant polymorphism via Ollama’, ‘Anti-analysis: 48–96 h delay, immediate execution in CI, AES-GCM encryption, in-memory execution’]
IOC
{‘malicious_packages’: [‘claud-code@0.2.1’, ‘cloude-code@0.2.1’, ‘cloude@0.3.0’, ‘crypto-locale@1.0.0’, ‘crypto-reader-info@1.0.0’, ‘detect-cache@1.0.0’, ‘format-defaults@1.0.0’, ‘hardhta@1.0.0’, ’locale-loader-pro@1.0.0’, ’naniod@1.0.0’, ’node-native-bridge@1.0.0’, ‘opencraw@2026.2.17’, ‘parse-compat@1.0.0’, ‘rimarf@1.0.0’, ‘scan-store@1.0.0’, ‘secp256@1.0.0’, ‘suport-color@1.0.1’, ‘veim@2.46.2’, ‘yarsg@18.0.1’], ’npm_aliases’: [‘official334’, ‘javaorg’], ’emails’: [‘official334@proton.me’, ‘JAVAorg@proton.me’], ‘github’: {‘user’: ‘official334’, ‘repo_action’: ‘ci-quality/code-quality-check (tags v1, v1.0.0)’, ‘usage’: ‘uses: ci-quality/code-quality-check@v1’, ‘injected_file’: ‘.github/workflows/quality.yml’}, ‘c2_exfil’: [‘https://pkg-metrics.official334.workers.dev/exfil’, ‘https://pkg-metrics.official334.workers.dev/drain’], ‘dns’: [‘freefan.net’, ‘fanfree.net’], ‘dga_tld’: [‘cc’, ‘io’, ‘xyz’, ’top’, ‘pw’, ’tk’, ‘ws’, ‘gg’, ’ly’, ‘mx’], ‘crypto_loader_artifacts’: {‘aes_256_gcm_iv_b64’: ‘dko6mG8AmQVECvVP’, ’tag_b64’: ‘/6rzsm9K+mflC4uguMJriA==’, ‘aes_key_hex’: ‘5ce544f6…460395c’, ‘sha_256_stage2’: ‘5440e1a4…9ae116e4’}, ‘misc’: {‘drain_bearer’: ‘fa31c223…4466cafb’, ‘github_url_model’: “https://github.com/node-util-${randomBytes(3).toString('hex')}/…”, ‘verdaccio_registry’: ‘http://localhost:4873’}}
🔗 Source originale : https://socket.dev/blog/sandworm-mode-npm-worm-ai-toolchain-poisoning