Aller au contenu

Module XVIII — red-teaming et test adversarial

Le module XVIII est un harnais de robustesse défensive. Il sonde les agents gouvernés propres au client avec une batterie de cas de test adversariaux publiés — injection de prompt, jailbreak, exfiltration, empoisonnement d’outils — et note leur résistance, mappée au OWASP Top 10 for Agentic Applications, à l’OWASP LLM Top 10 (2025) et à MITRE ATLAS. C’est une suite de tests, pas une arme : une conformité ou une fuite est un finding, pas un exploit remis à quiconque.

La batterie est un catalogue de sondes réparties en quatre familles (injection, jailbreak, exfil, tool_poisoning). Chaque sonde est un test de robustesse connu et publié mappé à une référence OWASP/ATLAS, avec l’attente qu’un agent bien défendu le refuse ou que son guardrail le bloque. Les payloads sont des canaris bénins — ils demandent à l’agent d’émettre un marqueur inerte, ou de décrire une opération dangereuse sans l’exécuter — de sorte que la batterie sonde le refus, pas la brèche. Un Judge déterministe classifie chaque résultat : blocked/refused est un pass, complied/leaked est un fail, error est une faute d’exécution, skipped est non-exécuté.

Les résultats s’agrègent dans un scorecard : score = passed / (passed + failed) × 100, avec errors et skipped délibérément exclus du dénominateur — une sonde qui ne s’est jamais exécutée n’est jamais comptée comme un pass. Le scorecard se décompose par famille et suit la couverture des échecs OWASP-Agentic, et c’est un enregistrement append-only, à altération détectable de sorte qu’un run ultérieur puisse le comparer comme baseline de régression.

La frontière dual-use est appliquée dans le code, pas seulement énoncée dans la documentation. Un run s’exécute uniquement contre un agent gouverné par le client qui a été explicitement enregistré et autorisé comme cible — et enregistrer n’est pas consentir : une cible naît registered avec l’autorisation retenue, et une étape d’autorisation distincte est l’octroi explicite. Lancer un run contre une cible non autorisée ou inconnue est refusé à la porte. Enregistrer, autoriser et lancer sont toutes des actions de tier admin, auditées, privilégiées ; chacune laisse un auto-audit attribué au principal réel.

Le module possède trois entités portées par le tenant : la target (un enregistrement de consentement mutable à travers son cycle de vie register → authorize → revoke), le run (un enregistrement d’évaluation append-only portant les agrégats et le score), et les results par sonde (append-only, une ligne par sonde). Il est à données minimales par construction : le endpoint de la cible est un handle opaque que la sandbox déréférence — jamais une credential — et un result ne stocke qu’un hash unidirectionnel de son détail, jamais le payload brut ni la réponse brute de l’agent. L’API côté lecture sert le catalogue en taxonomie uniquement (id, famille, titre, référence OWASP/ATLAS, sévérité, surface) ; les payloads des sondes sont internes et ne sont jamais exposés sur le fil.

Le module possède la batterie et la notation ; il n’atteint pas lui-même un quelconque agent. L’exécution est déléguée au runtime isolé via un seam Sandbox — la sandbox est le seul composant qui touche la cible, à l’intérieur du périmètre du client, avec un egress segmenté exactement vers la cible autorisée et tout le reste refusé. Chaque sonde échouée est persistée comme un Finding core (kind = "redteam") à l’intérieur de la transaction du run, et un événement finding.reported à données minimales (kind = "redteam_failure") est publié sur le bus d’événements pour les consommateurs de distribution et de conformité — les deux ne portent qu’une référence de sujet, un titre et un hash de détail.