Les denylists de commandes sont la mauvaise défense pour les agents IA en terminal
Une étude de l'Ohio State du 20 juin 2026 a passé 1 709 denylists de commandes d'agents réels dans un détecteur de contournement automatique : 69 à 98,6 % échouent à bloquer les opérations qu'elles prétendent interdire.
De quoi s’agit-il ?
Le 20 juin 2026, Chuyang Chen et Zhiqiang Lin (The Ohio State University) ont publié One Goal, Many Commands: Characterizing Denylist Fragility in AI Agents (arXiv 2606.15549). C’est la première étude systématique d’un contrôle sur lequel s’appuient fortement la plupart des agents de codage en terminal : la denylist de commandes, la liste des commandes shell qu’un agent refuse d’exécuter.
Le constat est sans détour. En appliquant un pipeline automatique à 1 709 denylists réelles collectées sur GitHub — 13 332 règles au total — les auteurs rapportent qu’entre 69,0 % et 98,6 % de ces denylists sont « fragiles » : elles échouent à bloquer des opérations qu’elles avaient explicitement pour but de bloquer. Même la denylist livrée par défaut avec un agent largement utilisé, maintenue par ses propres développeurs, laisse passer des commandes qui atteignent le résultat interdit par un autre chemin.
Le résultat relève de la catégorie « exécution de code inattendue » (ASI05) de l’OWASP Top 10 for Agentic Applications (2026) et a figuré parmi les faits marquants du digest coding-agent de juillet 2026 d’Adversa.
Comment ça marche
Les agents en terminal comme Claude Code et Codex encadrent l’exécution shell par un mécanisme à trois listes : une allowlist de commandes manifestement sûres s’exécute automatiquement, une denylist de commandes manifestement dangereuses est refusée d’emblée, et tout le reste tombe dans une « ask-list » escaladée vers un humain ou un juge LLM pour approbation.
Deux faits font de la denylist l’élément porteur du dispositif. D’abord, les commandes denylistées sont censées être catégoriquement dangereuses — le refus doit être absolu. Ensuite, l’article cite des données montrant que les utilisateurs approuvent environ 93 % des demandes d’exécution de commande : la fatigue décisionnelle réduit donc l’ask-list à une allowlist de fait. Si la denylist fuit, il ne reste plus grand-chose pour tenir la ligne.
Et elle fuit structurellement, car une denylist énumère des chaînes de caractères alors qu’un système d’exploitation offre de nombreux chemins vers le même effet. Une règle qui bloque un nom de commande ne fait rien contre un utilitaire moins connu de capacité équivalente, ni contre un outil multi-usage légitime invoqué dans un mode qui atteint le même résultat. L’outillage de l’étude, ShellSieve, utilise un LLM pour proposer des contournements candidats pour chaque opération refusée, puis les confirme en les exécutant dans un bac à sable et en observant les effets de bord laissés — sans supposition, sans faux positif. Les deux causes racines confirmées statistiquement sont exactement celles-ci : les auteurs omettent des commandes obscures qu’ils n’ont jamais rencontrées, et ils laissent délibérément hors liste des commandes multi-usage pour préserver leurs usages bénins, sans réaliser que ces mêmes commandes servent aussi de contournement.
Les auteurs quantifient aussi le piège de maintenance : compléter une denylist fragile pour qu’elle bloque réellement ses opérations cibles exige, en moyenne, 217 commandes supplémentaires — une course à l’armement ingagnable face à une surface de commandes ouverte.
Pourquoi c’est important
Ce n’est pas un bug isolé d’un produit ; c’est un jugement sur une catégorie entière de contrôle. La denylist est la première défense intuitive vers laquelle se tournent les équipes qui branchent un agent sur un shell, et c’est celle que ces données désignent comme la moins fiable. Dans une boucle d’agent de codage autonome, l’opération de l’autre côté d’une denylist qui fuit n’est pas une boîte de dialogue d’avertissement — c’est une suppression de fichiers, un accès à des identifiants, une exfiltration réseau ou un point d’ancrage que l’agent exécute lui-même sur l’hôte, avec les privilèges de l’utilisateur.
Le problème s’aggrave avec l’autonomie. Un humain qui tape des commandes est un adversaire lent et délibéré. Un agent qui synthétise des commandes pour satisfaire une instruction injectée ou mal formée peut énumérer les formulations alternatives plus vite qu’aucune blocklist maintenue à la main ne peut grandir pour les couvrir.
Défenses
Le cadrage de l’article indique lui-même la voie : cesser de traiter la denylist comme la frontière principale.
- Préférez les allowlists aux denylists pour tout ce qui a un vrai rayon d’impact. Une allowlist échoue en position fermée — une commande inconnue est refusée par défaut. Une denylist échoue en position ouverte — une commande inconnue s’exécute. Pour les contextes à fort impact, énumérez ce qui est permis, pas ce qui est interdit.
- Appliquez au niveau de l’OS, pas dans la chaîne de caractères. Un contrôle qui inspecte du texte sera toujours en retard sur la sémantique du shell. Les contrôles au niveau du noyau et des conteneurs — seccomp, montages restreints, absence d’identifiants ambiants, allow-lists d’egress — bornent ce que n’importe quelle commande peut faire, quelle que soit son écriture.
- Isolez la surface d’exécution de l’agent. Des environnements éphémères et isolés, à privilèges minimaux sur le système de fichiers et le réseau, transforment un contournement de denylist d’une compromission en un incident contenu. C’est la direction vers laquelle converge la recherche coding-agent de juillet 2026.
- Ne comptez pas sur l’approbation humaine comme filet de sécurité. Avec ~93 % d’approbation systématique, l’ask-list n’est pas une vraie barrière. Réservez les demandes aux actions réellement rares et réellement critiques, pour qu’une demande porte encore un signal.
- Si vous gardez une denylist, testez-la de façon adversariale. La découverte automatique de contournements, du type décrit par cet article, a sa place en CI, pour que la couverture réelle d’une denylist soit mesurée plutôt que supposée.
Statut
| Élément | Référence | Date | Notes |
|---|---|---|---|
| Étude fragilité denylist | arXiv 2606.15549 v2 | 2026-06-20 | Chen & Lin, Ohio State ; 69,0–98,6 % des denylists fragiles |
| Corpus analysé | — | 2026-06 | 1 709 denylists réelles, 13 332 règles issues de GitHub |
| Chiffre fatigue d’approbation | cité dans l’article | 2026 | ~93 % des demandes de commande approuvées |
| Catégorie | OWASP Top 10 for Agentic Apps 2026 | 2026 | ASI05 — exécution de code inattendue |
Il s’agit d’une caractérisation de recherche, pas d’un exploit divulgué contre un produit nommé, et l’article ne fournit aucun payload de contournement prêt à copier. Sa leçon opérationnelle est indépendante du modèle et de l’éditeur : si la sûreté d’un agent doté d’un shell repose sur une liste de commandes qu’il refuse d’exécuter, cette sûreté est, au vu de ces données, largement une illusion — et le correctif réside dans l’isolation et le moindre privilège, pas dans une blocklist plus longue.