Comment tester un scanner de securite quand l'attaquant connait les regles ? On cree les attaques soi-meme, on mesure ce qui passe a travers, et on corrige. 7 campagnes, 107 echantillons, et un score pre-tuning qui raconte l'histoire vraie.
La methodologie
Le cycle est toujours le meme :
- Geler les regles - aucune modification du scanner
- Creer les echantillons - techniques d'evasion basees sur des attaques reelles documentees
- Scanner avec les regles gelees - enregistrer les scores bruts
- Corriger les detections - ajouter/modifier les regles
- Verifier zero regression - les corrections ne doivent casser aucun test existant
Le score pre-tuning est la metrique la plus honnete. Il mesure la capacite de generalisation sur des patterns jamais vus pendant le developpement.
Les 7 campagnes
Vague 1 - Le baseline (20 echantillons)
Score pre-tuning : ~14%. Le scanner ne detectait presque rien. Les patterns de base (require() obfusque, DNS exfiltration, staged payload) passaient a travers. Corrections massives du scanner AST et dataflow. 5 nouvelles regles. Resultat post-tuning : 20/20.
Vague 2 - Techniques emergentes (5 echantillons)
Score pre-tuning : 0%. Template literal obfuscation, proxy env intercept, nested payload, dynamic import, websocket exfil - rien n'etait couvert. Le pire score de toutes les campagnes. Resultat post-tuning : 25/25.
Vague 3 - Attaques reelles 2025-2026 (5 echantillons)
Score pre-tuning : 60%. Premiere amelioration significative. Les techniques testees :
- AI agent weaponization - invocation de Claude/Gemini avec
--dangerously-skip-permissions(pattern s1ngularity/Nx) - AI config injection - injection de prompts dans
.cursorrules,CLAUDE.md(pattern ToxicSkills) - Zero-deps RDD - inline
https.get+eval()dans postinstall (pattern PhantomRaven) - Discord webhook exfil - credentials vers webhook Discord (pattern Shai-Hulud)
- Background fork - preinstall + fork detache + vol de credentials (pattern StepSecurity)
Cette vague a donne naissance au 13eme scanner : ai-config.js, dedie a la detection d'injection de prompts dans les fichiers de configuration d'agents IA.
Holdout v1 a v5 - Le test de generalisation (50 echantillons)
5 batches de 10 echantillons, chacun cree avec les regles gelees. C'est la mesure de generalisation pure :
| Batch | Score pre-tuning | Techniques |
|---|---|---|
| Holdout v1 | 30% (3/10) | Charcode reconstruction, proxy getter, stream hijack, workflow inject |
| Holdout v2 | 40% (4/10) | Env var reconstruction, lifecycle curl, readable stream hijack |
| Holdout v3 | 60% (6/10) | DNS TXT payload, steganography, reverse shell JS pur, require cache poison |
| Holdout v4 | 80% (8/10) | Desobfuscation : base64-require, charcode-fetch, hex-array-exec |
| Holdout v5 | 50% (5/10) | Inter-module : EventEmitter, stream pipeline, class method exfil |
La tendance 30% → 40% → 60% → 80% montre une amelioration constante de la generalisation. La chute a 50% au holdout v5 est attendue : c'etait un scanner entierement nouveau (module-graph) teste pour la premiere fois.
Vague 4 - Les 5 bypasses (5 echantillons)
Score pre-tuning : 0%. Les 5 techniques d'evasion les plus vicieuses :
| Technique | Score pre-fix | Source |
|---|---|---|
Concatenation .gi + t → .git | 3 | SANDWORM_MODE |
| Commandes node-gyp legitimes | 3 | NeoShadow / Aikido |
new Function() sans flag exec | 16 | buildrunner-dev / Veracode |
| Chemin tasks.json via retour fonction | 28 | StegaBin / FAMOUS CHOLLIMA |
Chemins dynamiques os.homedir() | 3 | SANDWORM_MODE |
La correction cle : resolveStringConcat(), une fonction recursive qui resout les BinaryExpression avec operateur +. .gi + t → .git. Technique d'evasion redoutablement simple mais efficace contre tout pattern matching statique.
Autre lecon : quand la resolution de chemins AST echoue, la detection par co-occurrence au niveau contenu est un filet de securite efficace. Si un fichier mentionne tasks.json ET runOn ET writeFileSync, c'est suspect independamment de la construction des chemins.
Red Team DPRK - Techniques nord-coreennes (10 echantillons)
10 echantillons simulant les techniques observees dans les campagnes Lazarus/APT38 :
- 5 echantillons pure API multi-fichiers - exfiltration repartie sur plusieurs modules avec imports locaux
- 5 echantillons evasion eval - eval factory,
.call.call(eval),require(/regex/.source), charcode arithmetique, object-method-alias
Cette campagne a donne naissance au graphe d'intention (analyse de coherence source-sink intra-fichier) et a 8 nouvelles regles.
Red Team v7 - Derniere campagne (corrections)
3 corrections de faux positifs sur les nouvelles regles + 3 quick wins ameliorant la detection sur des cas limites. Alignement final des metriques pour le benchmark Datadog.
Resultats finaux
| Metrique | Valeur |
|---|---|
| Echantillons adversariaux | 67 |
| Holdouts | 40 |
| Total | 107 |
| ADR (score ≥ 20) | 96.3% (103/107) |
| Misses documentes | 4 (limites acceptees) |
Sources des techniques
Toutes les techniques sont basees sur des attaques reelles documentees :
- Snyk : ToxicSkills, s1ngularity, Clinejection
- Sonatype : PhantomRaven (zero-deps dropper)
- Datadog Security Labs : Shai-Hulud 2.0 (workflow injection)
- Unit 42 : Shai-Hulud (credential exfil, dead man's switch)
- Check Point : Shai-Hulud 2.0 (Discord webhook exfil)
- StepSecurity : s1ngularity (AI agent abuse)
- Socket.dev : Mid-year supply chain report 2025
- Sygnia : chalk/debug sept 2025 (prototype hooking)
Lecon
Le score pre-tuning est la seule metrique honnete de generalisation. Le score post-tuning (100%) est tautologique - on a corrige ce qu'on savait casse. La progression 14% → 0% → 60% → 30% → 40% → 60% → 80% → 50% montre les oscillations reelles : chaque nouveau type de technique revele des angles morts, meme quand les corrections precedentes ont ameliore la couverture generale.
L'ADR de 96.3% signifie que 4 echantillons passent encore a travers. Et c'est normal - un attaquant suffisamment motive trouvera toujours une technique non couverte. L'objectif n'est pas 100%, c'est de rendre l'evasion couteuse.