# Guide de détection et remédiation : compromission npm jscrambler (IronWorm)

Ce guide s'adresse à quelqu'un qui doit vérifier/nettoyer une machine, pas à des analystes. Il s'appuie sur [`jscrambler-npm-supplychain.md`](jscrambler-npm-supplychain.md) ; ce que je n'ai pas vérifié moi-même (et qui vient seulement de sources tierces) est signalé comme tel.

## 1. Suis-je concerné ?

Vous êtes concerné si un projet Node.js sur cette machine a installé une des versions suivantes du package `jscrambler` entre le **11/07/2026 15:12 UTC et 18:12 UTC** :

```
8.14.0, 8.16.0, 8.17.0, 8.18.0, 8.20.0
```

(8.15.0 et les versions ≤8.13.0/≥8.22.0 sont saines.)

### Vérification rapide

```bash
# Cherche toutes les installations de jscrambler sur le système, versions incluses
find / -path "*/node_modules/jscrambler/package.json" -exec grep -H '"version"' {} \; 2>/dev/null

# Si un gestionnaire de version Node est utilisé, répéter dans chaque environnement
# (nvm, volta, asdf, etc. isolent souvent des node_modules différents)
```

Ou, avec les règles YARA fournies dans ce dossier ([`tools/ironworm.yar`](tools/ironworm.yar)) :

```bash
yara -r tools/ironworm.yar /chemin/vers/node_modules/
```

Un match sur `NPM_jscrambler_IronWorm_container` ou `NPM_jscrambler_IronWorm_js_loader` confirme la présence du code malveillant, indépendamment du numéro de version exact installé.

## 2. Signes d'infection active

**Persistance Windows** (que j'ai confirmée dans le binaire, template XML complet trouvé en clair dans `.rdata`, voir jscrambler-npm-supplychain.md §7.1) : tâche planifiée **cachée** (`<Hidden>true</Hidden>`), relance toutes les minutes (`PT1M`) jusqu'à 999 tentatives (`<RestartOnFailure>`).
```powershell
Get-ScheduledTask | Where-Object { $_.Settings.Hidden -eq $true } | Format-List TaskName, Actions
```

**Persistance macOS** (idem, non revérifiée directement) : LaunchAgent avec `RunAtLoad`/`KeepAlive`, intervalle ~30s.
```bash
ls -la ~/Library/LaunchAgents/ /Library/LaunchAgents/
# inspecter tout .plist non reconnu, chercher RunAtLoad + KeepAlive + StartInterval~30
```

**Linux** : aucun mécanisme de persistance identifié dans cette investigation à ce stade (ni par moi, ni par les sources tierces consultées), **n'en déduisez pas qu'il n'y en a pas**, juste que ça reste une inconnue ouverte (voir jscrambler-npm-supplychain.md §9).

**Toutes plateformes** : le binaire natif dropped est écrit dans le répertoire temporaire système (`os.tmpdir()`) sous un nom aléatoire commençant par un point (`.xxxxxxxx`, ou `.xxxxxxxx.exe` sur Windows). Cherchez des exécutables récents et non reconnus dans :
```
Linux/macOS : /tmp/.* 
Windows     : %TEMP%\.* 
```

## 3. Nettoyage

1. **Coupez l'accès réseau de la machine avant toute autre action** si une exécution du payload est suspectée (processus persistant actif), le protocole C2 confirmé (`{"t":"out"/"done",...}`, voir jscrambler-npm-supplychain.md §6) suggère une exfiltration active tant que le process tourne.
2. Tuez tout processus correspondant à un binaire suspect trouvé en §2 (nom aléatoire dans le répertoire temp).
3. Supprimez la tâche planifiée Windows / le LaunchAgent macOS identifiés en §2.
4. Supprimez `node_modules/jscrambler` (et tout `package-lock.json`/`yarn.lock`/`pnpm-lock.yaml` qui référence encore une version malveillante) dans **tous** les projets de la machine, pas seulement celui repéré en premier.
5. Réinstallez `jscrambler@8.22.0` ou plus récent uniquement après l'étape 4.
6. **Ne faites pas confiance à la machine elle-même pour la suite.** Le GHSA officiel est explicite : une machine ayant exécuté ce code doit être considérée comme totalement compromise, un simple retrait du package ne garantit pas l'absence d'autres implants posés par le payload une fois exécuté.

## 4. Rotation des secrets : depuis une AUTRE machine

À faire uniquement depuis un poste **non compromis**, jamais depuis la machine infectée elle-même :

| Catégorie | Action |
|---|---|
| Mots de passe/cookies navigateur (Chrome/Chromium/Brave/Edge) | Changer tous les mots de passe enregistrés, déconnecter toutes les sessions actives des comptes concernés |
| Bitwarden (et autres gestionnaires de mots de passe utilisant LevelDB accessible) | Changer le mot de passe maître, vérifier l'historique de connexion du compte |
| Steam | Déconnecter toutes les sessions actives, changer le mot de passe, vérifier l'historique de connexion |
| AWS (Secrets Manager, SSM Parameter Store, credentials de rôle EC2/IMDS) | Faire tourner (rotate) toutes les clés IAM et secrets accessibles depuis la machine, réviser les rôles IAM attachés à toute instance EC2 concernée |
| HashiCorp Vault | Révoquer les tokens/leases émis à la machine concernée, faire tourner les secrets lus |
| Discord, Slack, VS Code (via extraction ASAR Electron) | Déconnecter les sessions, changer les mots de passe, régénérer les tokens d'application si applicable |
| Wallets crypto (seed phrases BIP-39) | **Si une seed phrase a pu être stockée en clair ou copiée/collée sur la machine infectée, considérer les fonds comme compromis et transférer vers un nouveau wallet créé sur une machine saine** |
| Token de publication npm (si la machine publie des packages) | Révoquer et régénérer immédiatement, c'est exactement le vecteur d'entrée initial de cette compromission |

## 5. Signal réseau : trafic Tor sortant

Le C2 réel (confirmé par une source tierce, JFrog, voir jscrambler-npm-supplychain.md §7.4, que je n'ai pas vérifié moi-même) passe par un **service caché Tor** : le malware télécharge et lance son propre démon Tor local, puis fait du beaconing HTTP à l'intérieur du tunnel chiffré. Ça veut dire :

- Il n'y a **pas de domaine ou IP C2 fixe à bloquer**, bloquer une IP ne sert à rien contre un C2 Tor
- Le signal de détection réseau le plus fiable est la **présence de trafic Tor sortant** (port 9001/9050 typiques, ou trafic vers des relais Tor connus) depuis une machine qui ne devrait normalement pas en faire
- Si votre organisation bloque déjà Tor par politique, une alerte sur ce blocage précis, sur une machine de développement, est un signal fort

## 6. Ce qui n'est pas couvert par ce guide

- Persistance Linux (non confirmée, §2)
- Le mécanisme d'auto-propagation éventuel vers d'autres packages (non tracé, jscrambler-npm-supplychain.md §8)
- L'adresse `.onion` réelle du C2 (jamais obtenue, ni par moi ni par les sources consultées, la config qui la contiendrait reste chiffrée)

Ce document sera mis à jour si ces inconnues sont levées.
