← Blog

Comment tester un scanner de sécurité quand l'attaquant connaît les règles ? On crée les attaques soi-même, on mesure ce qui passe à travers, et on corrige. 7 campagnes, 107 échantillons, et un score pre-tuning qui raconte l'histoire vraie.

La méthodologie

Le cycle est toujours le même :

  1. Geler les règles - aucune modification du scanner
  2. Créer les échantillons - techniques d'évasion basées sur des attaques réelles documentées
  3. Scanner avec les règles gelées - enregistrer les scores bruts
  4. Corriger les détections - ajouter/modifier les règles
  5. Vérifier zéro régression - les corrections ne doivent casser aucun test existant

Le score pre-tuning est la métrique la plus honnête. Il mesure la capacité de généralisation sur des patterns jamais vus pendant le développement.

Les 7 campagnes

Vague 1 - Le baseline (20 échantillons)

Score pre-tuning : ~14%. Le scanner ne détectait presque rien. Les patterns de base (require() obfusqué, DNS exfiltration, staged payload) passaient à travers. Corrections massives du scanner AST et dataflow. 5 nouvelles règles. Résultat post-tuning : 20/20.

Vague 2 - Techniques émergentes (5 échantillons)

Score pre-tuning : 0%. Template literal obfuscation, proxy env intercept, nested payload, dynamic import, websocket exfil - rien n'était couvert. Le pire score de toutes les campagnes. Résultat post-tuning : 25/25.

Vague 3 - Attaques réelles 2025-2026 (5 échantillons)

Score pre-tuning : 60%. Première amélioration significative. Les techniques testées :

  • 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 détaché + vol de credentials (pattern StepSecurity)

Cette vague a donné naissance au 13ème scanner : ai-config.js, dédié à la détection d'injection de prompts dans les fichiers de configuration d'agents IA.

Holdout v1 à v5 - Le test de généralisation (50 échantillons)

5 batches de 10 échantillons, chacun créé avec les règles gelées. C'est la mesure de généralisation pure :

BatchScore pre-tuningTechniques
Holdout v130% (3/10)Charcode reconstruction, proxy getter, stream hijack, workflow inject
Holdout v240% (4/10)Env var reconstruction, lifecycle curl, readable stream hijack
Holdout v360% (6/10)DNS TXT payload, stéganographie, reverse shell JS pur, require cache poison
Holdout v480% (8/10)Désobfuscation : base64-require, charcode-fetch, hex-array-exec
Holdout v550% (5/10)Inter-module : EventEmitter, stream pipeline, class method exfil

La tendance 30% → 40% → 60% → 80% montre une amélioration constante de la généralisation. La chute à 50% au holdout v5 est attendue : c'était un scanner entièrement nouveau (module-graph) testé pour la première fois.

Vague 4 - Les 5 bypasses (5 échantillons)

Score pre-tuning : 0%. Les 5 techniques d'évasion les plus vicieuses :

TechniqueScore pre-fixSource
Concaténation .gi + t.git3SANDWORM_MODE
Commandes node-gyp légitimes3NeoShadow / Aikido
new Function() sans flag exec16buildrunner-dev / Veracode
Chemin tasks.json via retour fonction28StegaBin / FAMOUS CHOLLIMA
Chemins dynamiques os.homedir()3SANDWORM_MODE

La correction clé : resolveStringConcat(), une fonction récursive qui résout les BinaryExpression avec opérateur +. .gi + t.git. Technique d'évasion redoutablement simple mais efficace contre tout pattern matching statique.

Autre leçon : quand la résolution de chemins AST échoue, la détection par co-occurrence au niveau contenu est un filet de sécurité efficace. Si un fichier mentionne tasks.json ET runOn ET writeFileSync, c'est suspect indépendamment de la construction des chemins.

Red Team DPRK - Techniques nord-coréennes (10 échantillons)

10 échantillons simulant les techniques observées dans les campagnes Lazarus/APT38 :

  • 5 échantillons pure API multi-fichiers - exfiltration répartie sur plusieurs modules avec imports locaux
  • 5 échantillons évasion eval - eval factory, .call.call(eval), require(/regex/.source), charcode arithmétique, object-method-alias

Cette campagne a donné naissance au graphe d'intention (analyse de cohérence source-sink intra-fichier) et à 8 nouvelles règles.

Red Team v7 - Dernière campagne (corrections)

3 corrections de faux positifs sur les nouvelles règles + 3 quick wins améliorant la détection sur des cas limites. Alignement final des métriques pour le benchmark Datadog.

Résultats finaux

MétriqueValeur
Échantillons adversariaux67
Holdouts40
Total107
ADR (score ≥ 20)96.3% (103/107)
Misses documentés4 (limites acceptées)

Sources des techniques

Toutes les techniques sont basées sur des attaques réelles documentées :

  • 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)

Leçon

Le score pre-tuning est la seule métrique honnête de généralisation. Le score post-tuning (100%) est tautologique - on a corrigé ce qu'on savait cassé. La progression 14% → 0% → 60% → 30% → 40% → 60% → 80% → 50% montre les oscillations réelles : chaque nouveau type de technique révèle des angles morts, même quand les corrections précédentes ont amélioré la couverture générale.

L'ADR de 96.3% signifie que 4 échantillons passent encore à travers. Et c'est normal - un attaquant suffisamment motivé trouvera toujours une technique non couverte. L'objectif n'est pas 100%, c'est de rendre l'évasion coûteuse.