Ce qui doit vivre dans le code
La page sur le gating soutenait que le code doit posséder le seuil. Cette page va un cran plus loin : certaines vérifications ne devraient pas être demandées au modèle du tout.
L’énoncé de frontière le plus fort en public
La ligne la plus dure vient d’une implémentation de boucle d’agent :
Un appel d’outil avec un score de risque élevé force une autorisation humaine, et aucune probabilité ne peut l’annuler.
« Aucune probabilité ne peut l’annuler » mérite d’être isolé. Cela ne dit pas « la confiance doit être très élevée » — cela dit cette règle n’est pas dans l’espace des probabilités. La distinction compte :
- « Approuver automatiquement à ≥ 0.95 » est une règle de seuil — en principe une probabilité suffisamment élevée la franchirait.
- « Un risque élevé exige une approbation humaine » est une règle structurelle — vraie quel que soit ce que dit le modèle.
Ce n’est pas également fiable. Ton système doit dire explicitement quelles vérifications relèvent de l’une ou de l’autre, et il devrait y avoir autant de règles structurelles que possible.
Exécute d’abord les règles déterministes, ne donne au modèle que la zone grise
Une autre formulation du même patron :
Exécute d’abord les règles déterministes : tout ce qui peut être décidé est bloqué ou autorisé d’emblée, et le modèle n’est qu’un backend optionnel. Les commandes de routine sont décidées localement et ne sont jamais envoyées au modèle du tout.
Exécuter d’abord les règles a un bénéfice sous-estimé : cela réduit la surface d’attaque. Un juge qui dépend purement du modèle se comporte de façon imprévisible sous injection de prompt ; un juge qui exécute d’abord les règles confine l’injection à la petite tranche que les règles ne peuvent pas décider.
Un test d’injection publié rapporte 300 tentatives d’injection et dit franchement ce que la barrière a attrapé et ce qui est passé. C’est bien plus utile qu’une simple affirmation de « protection contre l’injection ».
Secrets et données sensibles : bloquer localement d’abord
Un détecteur de secrets expose clairement l’ordre :
| Cas | Traitement |
|---|---|
| Formats de secrets connus | Bloqués localement, jamais envoyés au modèle |
| Chaînes à haute entropie inconnues | Masquées d’abord, puis le texte masqué va au modèle |
| Le modèle dit ≥ 0.80 | Bloquer |
| Le modèle dit ≥ 0.30 | Demander à un humain |
| Modèle indisponible | Demander à un humain quand même |
Deux décisions à retenir :
- Le masquage vient d’abord. Tu ne peux pas envoyer quelque chose à un service externe pour découvrir s’il s’agit d’un secret. La vérification elle-même fuit.
- Un modèle mort demande quand même à un humain, plutôt que d’autoriser. C’est le fail-closed sous forme concrète — l’indisponibilité du service n’est pas une raison d’abaisser discrètement la barre de sécurité.
Mesuré : 6/6 secrets bloqués, 0/6 entrées bénignes bloquées à tort.
Plafonds budgétaires, reçus signés, audit
Certaines vérifications n’ont rien à voir avec ce que dit le modèle, mais doivent vivre dans le même système :
- Un runtime confie le blocage des commandes dangereuses et les plafonds budgétaires à du code déterministe, et consigne chaque verdict dans une chaîne de reçus signés Ed25519.
- Un autre confine le score de risque à une échelle 0–100 contrôlée par le code et signe chaque verdict avec ES256 (540 appels, 99.76% et 0 faux positifs à un seuil de 65–75).
Le but de la signature n’est pas de protéger contre le modèle — c’est qu’après coup tu puisses dire ce qui s’est passé. Quand une décision automatisée provoque un incident, « ce que le modèle a dit et ce que le code en a fait » doit être vérifiable indépendamment plutôt que relever de la confiance dans les journaux.
Filtrer l’injection à deux endroits
La conception d’une couche de garde mérite sa propre mention parce qu’elle nomme deux endroits facilement oubliés :
Filtre une fois avant l’exécution d’un appel d’outil, et de nouveau avant qu’un résultat d’outil ne soit lu par l’agent.
Le second est celui qu’on oublie. Filtre seulement l’entrée et une attaque peut se cacher dans ce que l’outil renvoie — une page récupérée, le contenu d’un fichier — qui entre dans le contexte en ayant contourné entièrement la vérification côté entrée.
Une règle apparentée d’une implémentation augmentée par la recherche : ne jamais produire un nombre qui n’apparaît pas dans les sources citées.
Isolation et permissions
Outre le filtrage du contenu, l’autre couche consiste à limiter le rayon d’impact : les chemins protégés passent toujours par une confirmation humaine ; l’exécution de l’agent s’exécute dans des espaces de travail isolés (une implémentation utilise Docker) ; les permissions des sous-agents sont séparées de celles du parent.
Un tableau de référence
| Vérification | De quel type | De quel côté elle tombe en cas d’erreur |
|---|---|---|
| Formats de secrets connus | Règle déterministe | Bloquer |
| Autorisation d’opération à risque élevé | Règle structurelle | Refuser (un humain doit approuver) |
| Approbation automatique des commandes en lecture seule | Règle de seuil | Retomber sur l’invite |
| Injection dans la sortie d’un outil | Filtre déterministe + modèle | Bloquer |
| « L’agent a-t-il fini ? » | Barrière d’efficacité | Autoriser (fail-open) |
| Vérifications de format et de style | Barrière d’efficacité | Autoriser |
La colonne du milieu est le point : plus on est près du haut, moins le modèle doit être impliqué.
En une phrase
Une vérification qui peut être annulée par une probabilité finira par l’être. Décide d’abord quelles vérifications n’ont pas le droit d’être annulées ; ne règle les seuils qu’ensuite.