Passer au contenu principal
Un agent qui a été injecté via un prompt, mal configuré ou simplement doté d’une trop grande latitude peut appeler des outils qu’il n’était jamais censé toucher — ou appeler un outil légitime avec des arguments dangereux : shell.exec avec rm -rf /, une API de paiement avec un montant de transfert excessif, un outil de base de données ciblant le réplica de production. C’est l’abus d’outil d’agent, et c’est l’un des risques les plus conséquents dans les systèmes agentiques parce que les appels d’outils ont des effets secondaires réels qui sont souvent irréversibles. L’Agent Firewall dispose de trois défenses en couches. Vous pouvez les déployer indépendamment ou en combinaison.

1. Liste blanche : refuser tout ce que vous n’avez pas explicitement autorisé

Le contrôle le plus fort est une liste blanche. Au lieu d’essayer d’énumérer chaque outil dangereux, vous énumérez les outils dont cet agent a légitimement besoin — et refusez tout le reste. C’est le référentiel zero trust. Une politique avec default_verdict: deny et des règles allow explicites pour chaque outil approuvé accomplit cela. Exemple : un agent qui devrait seulement lire depuis un CRM :
[
  {
    "priority": 10,
    "label": "allow crm reads",
    "tool_name_glob": "crm.get*",
    "verdict": "allow"
  },
  {
    "priority": 20,
    "label": "allow crm search",
    "tool_name_glob": "crm.search",
    "verdict": "allow"
  },
  {
    "priority": 9999,
    "label": "deny everything else",
    "tool_name_glob": "*",
    "verdict": "deny"
  }
]
Tout appel à shell.exec, db.delete, payment.transfer — qu’il soit émis intentionnellement ou déclenché par une instruction injectée — touche le catch-all * et retourne une erreur HTTP 400 firewall_blocked. L’agent voit une erreur d’outil structurée et ne peut pas réessayer (le block est marqué skip-retry), donc il ne peut pas boucler autour du refus.
Définissez le default_verdict de votre politique sur deny pour une application complète de la liste blanche. Avec le verdict par défaut audit, les appels non correspondants sont autorisés et journalisés mais pas bloqués — utile pendant le déploiement mais pas un contrôle de sécurité en soi.
Les patterns de glob vous permettent d’autoriser des familles entières d’outils avec une seule règle. Les patterns courants :
PatternCe qu’il couvre
crm.*Tous les outils dans l’espace de noms crm
*.readTout outil avec verbe read sur tous les serveurs
db.queryExactement cet outil
*Tout (utilisez pour votre deny catch-all)
La correspondance d’outils est premier-match-gagne dans l’ordre de priorité ascendant. Mettez vos règles allow spécifiques à des numéros de priorité bas et le deny catch-all à un numéro élevé.

2. Validation des arguments : autoriser l’outil, bloquer l’invocation dangereuse

Une liste blanche sur les noms d’outils est grossière — elle bloque shell.exec entièrement. Parfois vous voulez autoriser un outil mais contraindre comment il peut être appelé. Les clauses d’arguments vous permettent de correspondre sur des champs spécifiques à l’intérieur des arguments d’appels d’outils, en utilisant JSONPath et un ensemble d’opérateurs. Exemple : autoriser shell.exec mais bloquer rm -rf
{
  "priority": 10,
  "label": "block destructive rm",
  "tool_name_glob": "shell.exec",
  "args_match": {
    "clauses": [
      {
        "path": "$.command",
        "op": "regex",
        "value": "rm\\s+-[^\\s]*r[^\\s]*f|mkfs|dd\\s+if=|:\\(\\)\\{.*\\}"
      }
    ]
  },
  "verdict": "deny"
}
Cette règle se déclenche seulement quand shell.exec est appelé et que l’argument $.command correspond à la regex de commande destructrice. Un appel normal à shell.exec avec une commande sûre tombe sur la règle suivante (ou le verdict par défaut). Mettez cette règle à un numéro de priorité plus bas que toute règle générale allow shell.exec afin qu’elle se déclenche en premier. L’ensemble complet des opérateurs d’arguments :
OpérateurUtilisez-le quand
eqCorrespondance exacte sur une valeur scalaire (chaîne ou nombre)
containsCorrespondance de sous-chaîne — ex. $.query contains DROP TABLE
regexCorrespondance de pattern RE2 — sûr sur le chemin à chaud, pas de retour en arrière
inLa valeur doit être dans un tableau donné — ex. autoriser seulement des environnements spécifiques
cidr_matchAdresse IP dans un bloc CIDR — utile pour les vérifications de destination d’egress
gt / ltComparaison numérique — ex. $.amount gt 10000 pour les plafonds de paiement
Toutes les clauses dans un bloc args_match sont ET-ées. Si un chemin n’existe pas dans les arguments de l’appel, la clause évalue faux et la règle ne se déclenche pas — l’appel tombe sur la règle suivante ou le défaut. Exemple de garde de paiement — refuser tout appel d’outil de paiement avec un montant dépassant un seuil :
{
  "priority": 5,
  "label": "cap payment amount",
  "tool_name_glob": "payment.*",
  "args_match": {
    "clauses": [
      { "path": "$.amount_cents", "op": "gt", "value": 100000 }
    ]
  },
  "verdict": "deny"
}

3. Humain dans la boucle : mettez en attente les appels à enjeux élevés pour approbation

Pour les outils genuinement nécessaires mais à enjeux élevés — déclencher un déploiement, approuver un remboursement, envoyer un email en masse — vous pouvez exiger une signature humaine avant que l’appel ne continue. Le verdict pending_approval met l’appel en attente et retourne une réponse firewall_approval_pending à l’agent :
{
  "priority": 20,
  "label": "hold deployment calls for review",
  "tool_name_glob": "deploy.*",
  "verdict": "pending_approval"
}
L’agent (ou votre framework) interroge l’id d’approbation. Un relecteur approuve ou rejette depuis la console ou via un callback webhook. Si approuvé, l’agent re-soumet l’appel original avec le token d’approbation à usage unique et la passerelle le laisse passer une fois. pending_approval est compatible avec les clauses d’arguments — vous pouvez mettre en attente uniquement les invocations qui correspondent à un seuil, et laisser passer les routines :
[
  {
    "priority": 10,
    "label": "hold large deploys",
    "tool_name_glob": "deploy.release",
    "args_match": {
      "clauses": [
        { "path": "$.environment", "op": "eq", "value": "production" }
      ]
    },
    "verdict": "pending_approval"
  },
  {
    "priority": 20,
    "label": "allow staging deploys",
    "tool_name_glob": "deploy.*",
    "verdict": "allow"
  }
]

4. À quoi ressemble un appel bloqué

Un appel refusé sur la surface inbound (outil annoncé dans la requête) retourne HTTP 400 avec le code d’erreur firewall_blocked. La réponse inclut des metadata structurées — le label de règle correspondant, le code de raison et les facteurs de risque — et est marquée skip-retry afin qu’une boucle ne puisse pas marteler le même appel refusé. Un appel bloqué sur la surface response (le modèle a déjà émis tool_calls) retourne une erreur d’outil visible pour le modèle, lui donnant la chance de réagir — choisir un outil différent, demander à l’utilisateur, ou s’arrêter — au lieu de planter.

5. Ordre premier-match-gagne

L’ordre de priorité importe. Le moteur parcourt les règles dans l’ordre de priorité ascendant et s’arrête à la première correspondance. Un pattern courant :
PrioritéRègleVerdict
5shell.exec + regex destructricedeny
10shell.* (général)allow
20crm.*allow
9999* (catch-all)deny
La priorité 5 se déclenche avant la priorité 10 — donc shell.exec avec une commande destructrice est refusé même s’il y a un allow général pour shell.*. Sans le deny à faible priorité, la règle allow shell.* gagnerait en premier.

6. Déploiement sûr avec le mode shadow

Avant de passer une nouvelle politique en mode d’application, activez le mode shadow. La politique évalue chaque appel d’outil et journalise le verdict exactement comme elle le ferait en production, mais chaque verdict appliquant (deny, pending_approval, sanitize) est rétrogradé en audit — rien n’est bloqué. La raison dans le journal d’événements est préfixée [shadow] would deny afin que vous puissiez mesurer l’impact dans les vues Events et Runs. Une fois que vous avez confirmé que la politique se déclenche sur ce que vous attendez — et rien que vous n’avez pas voulu — désactivez le mode shadow. Le prochain appel est appliqué.
Le niveau d’autonomie tight applique le preset block_destructive_shell automatiquement. Si vous avez besoin d’une posture rapide sans rédiger de règles, appliquez tight depuis la console et il livre une politique de refus pour les appels shell destructeurs en une étape. Vous pouvez ensuite superposer vos propres règles de liste blanche par-dessus. Voir Niveaux d’autonomie.

7. Menaces associées

L’abus d’outil d’agent arrive rarement de manière isolée. Un appel d’outil non autorisé est souvent la conséquence d’un autre vecteur d’attaque :
  • Injection de prompt — un attaquant intègre des instructions dans le contenu récupéré qui orientent l’agent vers des outils qu’il n’était pas censé appeler.
  • Agence excessive — l’agent s’est vu accorder plus d’accès aux outils que sa tâche ne nécessite, rendant toute injection ou mauvaise configuration immédiatement dangereuse.
  • Le modèle de menace — comment l’abus d’outil s’inscrit dans la surface d’attaque complète des systèmes agentiques.
L’Agent Firewall est la couche d’application ; le principe du moindre privilège (listes blanches d’outils étroites, clés à portée limitée) est la posture de conception qui le rend efficace.

Référence des règles Firewall

Le langage de correspondance complet — globs d’outils, clauses d’arguments, tous les opérateurs, verdicts et l’API.

Vue d'ensemble du Firewall

Politiques, surfaces, niveaux d’autonomie, approbation HITL et observabilité.