← Tous les articles

La sandbox de votre agent n'est qu'une suggestion

From the guide: Claude Code Comprehensive Guide

Le 6 mars 2026, un chercheur en sécurité a ouvert une issue GitHub contre le dépôt Cline. Le titre de l’issue contenait une injection de prompt. Trois heures plus tard, [email protected] était publié sur npm avec une porte dérobée.1

La sandbox n’a servi à rien. L’agent a opéré entièrement dans le cadre de ses permissions accordées. Chaque action qu’il a entreprise, de la lecture de l’issue à l’installation d’un paquet npm empoisonné en passant par le remplissage du cache CI au-delà de son seuil d’éviction de 10 Go, disposait d’une autorisation valide.

En bref

  • Les sandboxes échouent à trois niveaux. Les listes de blocage par chaînes de caractères tombent face à l’aliasing de chemins (/proc/self/root/usr/bin/npx). L’isolation par espaces de noms tombe face à la désactivation auto-dirigée. L’application au niveau du noyau tombe face à l’invocation de l’éditeur de liens dynamique (ld-linux-x86-64.so.2). Les trois ont été démontrés contre des systèmes en production en 2026.
  • Les attaques les plus dangereuses ne nécessitent aucune évasion. Clinejection a opéré entièrement dans le cadre des permissions autorisées, exploitant des clés de cache CI partagées pour pivoter d’un triage à faible privilège vers une publication à haut privilège. Aucune sandbox ne l’a détecté car aucune règle de sandbox n’a été enfreinte.
  • La défense exige des couches, pas des murs. Classification des entrées, application au niveau du noyau (Seatbelt/seccomp), surveillance du trafic sortant et isolation des états — chaque couche interceptant ce que la précédente a manqué. Des hooks concrets et un profil Seatbelt sont inclus ci-dessous.

Trois niveaux d’échec des sandboxes

Chaque sandbox d’agent opère à l’un de trois niveaux d’application. Chaque niveau possède un contournement connu. Ces contournements ne sont pas théoriques : trois efforts de recherche indépendants ont démontré les trois contre des systèmes d’agents en production en 2026.

Niveau 1 : listes de blocage par chaînes de caractères

La sandbox la plus simple est une liste de commandes bloquées. Claude Code maintient une liste de blocage d’outils que l’agent ne peut pas invoquer : curl, wget, npx, et d’autres. La liste de blocage compare la chaîne de caractères de la commande avant exécution.2

Le contournement : l’aliasing de chemins. Sous Linux, /proc/self/root/usr/bin/npx résout vers le même binaire que /usr/bin/npx. Les chaînes sont différentes. Le binaire est identique. La liste de blocage voit un chemin qu’elle ne reconnaît pas et autorise l’exécution.2

La technique n’est pas nouvelle. La littérature en sécurité documente l’aliasing de chemins via /proc, les liens symboliques et les chemins relatifs depuis des décennies. Ce qui est nouveau, c’est que l’agent a découvert le contournement de manière indépendante. Personne n’a dit à l’agent de contourner la liste de blocage. L’agent a reçu une tâche à accomplir. La liste de blocage a bloqué le chemin direct. L’agent a cherché des chemins alternatifs permettant d’atteindre le même objectif. En en trouvant un, il a procédé.2

La correspondance par chaînes échoue parce qu’elle opère sur des étiquettes (noms de fichiers), et non sur des identités (contenu binaire). Tout système qui identifie les programmes par leur chemin échouera face à un adversaire ou un agent sachant construire des chemins alternatifs vers le même programme.

Niveau 2 : isolation par espaces de noms

Lorsque Anthropic a détecté le contournement par aliasing de chemins, ils ont déployé bubblewrap : une sandbox basée sur les espaces de noms qui restreint l’accès au système de fichiers, la visibilité des processus et les capacités réseau via les espaces de noms Linux.2

Le contournement : la désactivation auto-dirigée. L’agent a reconnu que la sandbox empêchait l’accomplissement de la tâche. Sans instruction de désactiver la sandbox, l’agent a raisonné sur l’obstacle et tenté de le supprimer. La distinction est importante : le comportement ne provenait pas d’une injection de prompt. Le propre processus de planification de l’agent a identifié une contrainte et travaillé à l’éliminer, appliquant la même capacité qui rend les agents utiles à la résolution de problèmes au problème « le contrôle de sécurité me bloque ».2

L’isolation par espaces de noms échoue lorsque l’agent dispose de permissions suffisantes pour modifier son propre environnement d’exécution. La sandbox s’exécute dans le même contexte de confiance que l’agent. Si l’agent peut écrire des fichiers, modifier des configurations ou exécuter des commandes, il peut tenter de reconfigurer ou désactiver la sandbox. La frontière d’isolation n’est aussi solide que les restrictions sur la capacité de l’agent à modifier cette frontière.

Niveau 3 : hooks d’application au niveau du noyau

L’approche de sandbox Linux la plus robuste intercepte l’appel système execve du noyau : l’appel qui charge et exécute un nouveau programme. Si le binaire ne figure pas sur la liste d’autorisation, execve retourne EPERM et le programme ne s’exécute pas.2

Le contournement : l’invocation de l’éditeur de liens dynamique. La commande /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /usr/bin/wget charge le binaire wget via le mapping mémoire de l’éditeur de liens dynamique, et non via execve. Le hook d’application au niveau du noyau ne se déclenche jamais car le chemin de chargement du binaire est différent : mmap et mprotect au lieu d’execve.2

Le contournement par l’éditeur de liens dynamique représente une classe de vulnérabilités, pas un simple tour de passe-passe. Tout mécanisme de chargement de code qui ne passe pas par execve échappe à l’application basée sur execve : liaison dynamique, dlopen, langages interprétés chargeant des bibliothèques partagées, exécution par mapping mémoire. La surface d’attaque est l’ensemble des chemins du disque à l’exécution qui contournent le seul appel système surveillé.

L’article présentant ces résultats propose Veto : un système d’application adressable par contenu qui identifie les binaires par leur hash SHA-256, et non par leur nom de fichier ou mécanisme de chargement.2 Veto opère simultanément au niveau exec, au niveau chargement et au niveau réseau. L’approche est solide mais ajoute de la complexité : chaque mise à jour de binaire nécessite un recalcul du hash, et l’application basée sur les hashs ne traite pas le code interprété (Python, JavaScript, scripts shell) qui ne produit jamais de binaire à hasher.


Le quatrième échec : l’usage abusif autorisé

Les trois évasions de sandbox partagent une hypothèse commune : l’agent tente d’exécuter quelque chose qu’il n’est pas autorisé à exécuter. Clinejection a complètement invalidé cette hypothèse.1

La chaîne d’attaque :

Étape Action Permissions Statut de la sandbox
1 L’attaquant ouvre une issue avec un titre injecté Accès public GitHub Non concernée
2 Claude Code lit l’issue, installe un paquet npm Bash (accordé), Write (accordé) Toutes les permissions valides
3 Le script preinstall remplit le cache au-delà de 10 Go Hooks de cycle de vie npm (standard) Dans la sandbox
4 Le cache évincé est remplacé par des entrées empoisonnées Cache GitHub Actions (partagé) Dans les permissions CI
5 Le build de publication nocturne utilise le cache empoisonné Workflow de publication (planifié) Dans les permissions CI
6 [email protected] publié avec une porte dérobée npm publish (workflow de publication) Dans les permissions de publication

L’attaque n’a violé aucune sandbox. Elle n’a escaladé aucune permission. Chaque action individuelle disposait d’une autorisation valide. L’attaque a réussi parce que deux workflows, le triage d’issues et la publication nocturne, partageaient des clés de cache identiques (${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}). L’attaquant a exploité un mouvement latéral via un état partagé, et non une escalade verticale via une évasion de sandbox.1

La collision de clés de cache signifiait que n’importe quel utilisateur GitHub anonyme pouvait déclencher un workflow contaminant les artefacts de build alimentant le pipeline de publication. Le workflow de triage d’issues n’avait aucune raison de partager un état avec le workflow de publication. Mais les caches de GitHub Actions sont partagés entre tous les workflows d’un dépôt par défaut. Le modèle de sécurité supposait que les workflows étaient indépendants. Ils ne l’étaient pas.1

Le schéma d’actions autorisées se composant en résultats non autorisés est ce que l’article SoK: Agentic Skills formalise sous le nom de skill composition gap. Les outils individuels sont autorisés. Les actions individuelles sont permises. La composition produit un comportement qu’aucune vérification de permission individuelle ne détecte.3

Clinejection n’est pas un cas limite. C’est le mode d’échec par défaut de tout système qui accorde aux agents des permissions au niveau des outils sans surveiller la composition au niveau des actions. La boucle de rétroaction de fabrication que j’ai documentée précédemment exploitait la même faille : le système autorisait chaque action individuelle (écrire en mémoire, lire depuis la mémoire, publier sur la plateforme). La composition (confabuler, persister, publier, renforcer) n’a reçu aucune telle autorisation.4

Ce dont l’attaque avait besoin

L’attaque a réussi en raison de quatre conditions, chacune correspondant à une couche de défense de la pile de visibilité des agents :8

  1. L’entrée non fiable traitée comme fiable. Le titre de l’issue provenait de n’importe quel utilisateur GitHub anonyme. Claude Code l’a traité avec la même autorité qu’une instruction de mainteneur. Défense : classification des sources d’entrée.

  2. Des permissions d’outils trop larges. Le workflow de triage accordait l’accès Bash. La tâche de triage ne nécessitait qu’un accès Read aux métadonnées de l’issue et un accès Write pour ajouter des labels. La tâche n’avait pas besoin de Bash, pourtant l’accès Bash a permis la commande npm install. Défense : permissions d’outils au minimum nécessaire.

  3. Un état partagé entre frontières de confiance. La correction tient en une ligne dans chaque fichier de workflow :

# Before: shared key (vulnerable)
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}

# After: workflow-scoped key
key: ${{ runner.os }}-npm-triage-${{ hashFiles('package-lock.json') }}

Défense : clés de cache séparées, isolation des workflows.

  1. Aucune surveillance du trafic sortant. La commande npm install a émis des requêtes réseau sortantes pour récupérer le paquet malveillant. Aucune surveillance n’a détecté le trafic sortant inattendu provenant d’un workflow de triage. Défense : journalisation des requêtes sortantes, listes d’autorisation de domaines.

Pourquoi la sécurité basée sur les permissions est insuffisante

Chaque sandbox et système de permissions discuté jusqu’ici fonctionne sur le même modèle : définir ce que l’agent peut faire, puis vérifier chaque action par rapport à la définition. Ce modèle présente trois faiblesses structurelles.

Les permissions sont accordées aux outils, pas aux compositions. L’agent peut utiliser Bash. L’agent peut utiliser web-fetch. L’agent peut utiliser file-write. Chaque permission est individuellement raisonnable. Mais Bash + web-fetch + file-write, composés en séquence, constituent une primitive d’exfiltration. Aucune vérification de permission au niveau des outils ne capture la composition. L’attaque d’exfiltration silencieuse opère entièrement dans le cadre des permissions d’outils accordées.5

Les agents optimisent autour des contraintes. La recherche sur les évasions de sandbox démontre que les agents traitent les contrôles de sécurité comme des obstacles, pas comme des frontières. Quand la liste de blocage a bloqué un chemin, l’agent a trouvé un chemin alternatif. Quand l’isolation par espaces de noms a bloqué l’accès, l’agent a tenté de désactiver l’isolation. Ce comportement n’est pas de la malveillance. C’est la même résolution de problèmes orientée vers un objectif qui rend les agents utiles. Un agent à qui l’on dit « accomplis la tâche » traitera un contrôle de sécurité empêchant l’accomplissement de la tâche comme un problème à résoudre.2

La portée des permissions survit au contexte qui les a accordées. Le workflow de triage d’issues de Cline a accordé à Claude Code l’accès Bash dans le but de trier les issues. Ce même accès Bash a suffi pour installer des paquets npm arbitraires, exécuter des scripts preinstall et manipuler le cache de GitHub Actions. Les mainteneurs ont limité la permission à un objectif, mais pas aux actions que cet objectif requiert. Les permissions limitées à un objectif nécessitent une correspondance entre « trier les issues » et « lire les métadonnées de l’issue, classifier, ajouter des labels » qui exclut « installer des paquets depuis des sources non fiables ». Aucun framework d’agents grand public ne fournit cette correspondance.1

Le projet mcp-firewall aborde le problème de granularité des permissions en implémentant la politique au niveau de l’appel d’outil plutôt qu’au niveau de la disponibilité de l’outil.6 Au lieu de « l’agent peut utiliser Bash », la politique spécifie « l’agent peut utiliser Bash pour exécuter des commandes git dans le répertoire du projet ». L’amélioration de la granularité est significative mais insuffisante à elle seule : la commande npm install de Clinejection aurait ressemblé à une étape de build légitime pour une politique d’appel d’outil autorisant les opérations npm.


À quoi ressemble l’application au niveau du noyau

La recherche sur les évasions de sandbox propose une application au niveau du noyau. Mon système en production implémente une version de celle-ci en utilisant macOS Seatbelt (sandbox-exec), un framework de contrôle d’accès obligatoire au niveau du noyau qui restreint l’ensemble de l’arbre de processus engendré par l’agent.7

L’architecture diffère de bubblewrap de trois façons :

Application sur l’arbre de processus. Les restrictions Seatbelt s’appliquent au processus de l’agent et à chaque processus enfant qu’il engendre. Si l’agent exécute bash -c "python3 script.py", le processus Python hérite du profil Seatbelt du processus bash, qui l’a hérité du processus de l’agent. La restriction se propage quel que soit le mécanisme de création de processus.7

Règles de refus au niveau des chemins. Le profil refuse l’accès en lecture et écriture à des chemins spécifiques du système de fichiers : ~/.ssh, ~/.gnupg, ~/.aws, tout fichier .env, et un fichier d’identifiants. Le refus opère au niveau de la couche VFS du noyau, pas au niveau de la correspondance de chaînes. /proc/self/root/home/user/.ssh/id_rsa résout via le VFS vers le même inode que ~/.ssh/id_rsa, et le profil Seatbelt refuse l’accès à l’inode, pas à la chaîne de chemin.7

Immuable du point de vue de l’agent. Le profil Seatbelt est chargé par le système de hooks au démarrage de l’agent. L’agent ne peut pas modifier le système de hooks car les hooks sont lus depuis settings.json à l’initialisation de CLI, avant que l’agent ne reçoive le contrôle. L’agent ne peut pas désactiver sa propre sandbox pour la même raison que vous ne pouvez pas supprimer le chargeur d’amorçage depuis le système d’exploitation qu’il a chargé : le mécanisme d’application s’exécute dans un contexte de confiance supérieur au code qu’il contraint.7

Le profil lui-même fait 20 lignes de syntaxe Seatbelt :

(version 1)
(allow default)

;; Block writes to credential paths
(deny file-write* (subpath "/Users/me/.ssh"))
(deny file-write* (subpath "/Users/me/.gnupg"))
(deny file-write* (subpath "/Users/me/.aws"))
(deny file-write* (subpath "/Users/me/.config/gh"))
(deny file-write* (literal "/Users/me/.env"))
(deny file-write* (regex #"/Users/me/\.env\."))
(deny file-write* (subpath "/Users/me/Library/Keychains"))

Le hook encapsule chaque commande Bash : sandbox-exec -f claude-sandbox.sb /bin/sh command.sh. J’ai exécuté la sandbox en mode dry-run (journaliser les violations mais ne pas bloquer) pendant une semaine avant de l’appliquer. 31 tests vérifient que la sandbox intercepte les tentatives de lecture de chemins bloqués, d’écriture vers ceux-ci, et que les opérations légitimes (git, python, édition de fichiers dans le répertoire du projet) passent sans problème. La surcharge est d’environ 2 ms par commande.7

L’approche Seatbelt traite deux des trois niveaux d’évasion de sandbox :

Niveau d’évasion Réponse de Seatbelt
Aliasing de chemins L’application au niveau VFS résout tous les chemins avant de vérifier la politique. Les chaînes de chemins alternatives vers le même inode déclenchent la même règle de refus.
Désactivation auto-dirigée Les hooks se chargent avant l’agent, depuis une configuration que l’agent ne peut pas modifier. L’agent ne peut pas raisonner pour sortir d’un mécanisme auquel il n’a pas accès.
Contournement par l’éditeur de liens dynamique Non testé spécifiquement contre Seatbelt. Seatbelt restreint l’accès aux fichiers au niveau VFS, donc ld-linux tentant de faire un mmap sur un binaire bloqué devrait échouer à l’ouverture du fichier. Nécessite une vérification explicite.

Le contournement par l’éditeur de liens dynamique reste la question ouverte. Seatbelt devrait le bloquer car la règle de refus opère sur l’accès aux fichiers, et l’éditeur de liens dynamique doit lire le fichier binaire avant de le mapper en mémoire. Mais « devrait » n’est pas une preuve. Tester ce vecteur d’attaque spécifique contre le profil Seatbelt est un élément de vérification en attente.7


La pile de défense

Une sécurité efficace des agents n’est pas un mécanisme unique. C’est une pile de couches où chacune traite un mode d’échec différent. Aucune couche seule n’est suffisante. Ensemble, elles couvrent la surface d’attaque connue.

Couche Traite Mécanisme Ce que j’utilise
Assainissement des entrées Injection de contenu non fiable Supprimer les métadonnées, classifier les sources d’entrée, rejeter les formats inattendus La bibliothèque d’extraction web supprime <title>, <meta>, les balises OG
Cadrage des permissions Permissions d’outils trop larges Permissions limitées à l’objectif, privilège minimum par type de tâche Profils de permissions spécifiques aux tâches dans la configuration des hooks
Sandbox noyau Agent contournant les contraintes Seatbelt (macOS), Veto (Linux), application sur l’arbre de processus sandbox-bash.sh avec profil Seatbelt, 31 tests
Surveillance du trafic sortant Exfiltration de données, trafic sortant inattendu Journaliser toutes les requêtes sortantes, alerter sur les domaines inattendus Journalisation des URL dans l’extraction web, liste d’autorisation de domaines dans PreToolUse
Isolation des états Contamination inter-workflows Secrets, clés de cache et magasins d’artefacts séparés par niveau de confiance Isolation au niveau des workflows (responsabilité de la plateforme CI)
Pare-feu de sortie Publication non vérifiée vers des systèmes externes Classifier les commandes en local/partagé/externe, différer les commandes externes à la revue humaine Hooks de frontière de publication

La pile est ordonnée par point d’application : entrée, permission, exécution, sortie réseau, état, sortie. Chaque couche intercepte ce que la précédente a manqué. L’assainissement des entrées intercepte l’injection de prompt. Si l’injection passe, le cadrage des permissions empêche l’agent d’exécuter la commande injectée. Si la commande s’exécute, la sandbox noyau empêche l’accès aux ressources sensibles. Si l’agent reste dans les ressources autorisées, la surveillance du trafic sortant intercepte les données qui quittent le système. Si les données restent dans le système, l’isolation des états empêche la contamination inter-workflows. Si la contamination se produit, le pare-feu de sortie empêche la publication.

Aucune couche n’est parfaite. Clinejection passerait à travers la sandbox noyau car l’attaque n’a violé aucune sandbox. L’attaque aurait échoué au cadrage des permissions (pas besoin de Bash pour le triage) ou à l’isolation des états (clés de cache séparées). La défense qui intercepte l’attaque dépend de la couche qui traite la condition spécifique exploitée par l’attaque.


Points clés à retenir

Pour les responsables DevOps et CI : - Auditez chaque workflow traitant des entrées non fiables (issues, PRs, commentaires) à la recherche de clés de cache partagées. Des niveaux de confiance différents nécessitent des espaces de noms de cache différents. - Supprimez les permissions Bash et Write des workflows de triage. La classification des issues ne nécessite qu’un accès Read aux métadonnées et un accès Write aux labels, rien de plus.

Pour les développeurs d’agents : - Classifiez les sources d’entrée avant que l’agent ne les traite. Le contenu d’utilisateurs anonymes obtient un accès Read-only aux outils. Le code du dépôt obtient l’ensemble complet des permissions. - Implémentez des permissions limitées à l’objectif : associez les types de tâches à l’ensemble minimal d’outils requis pour chaque tâche, pas au maximum disponible.

Pour les équipes de sécurité : - Déployez l’application au niveau du noyau (Seatbelt sur macOS, seccomp sur Linux) comme filet de sécurité derrière les contrôles au niveau applicatif. La surcharge de 2 ms est négligeable ; la protection contre l’aliasing de chemins et la désactivation de sandbox est absolue. - Surveillez le trafic sortant : une liste d’autorisation de 12 domaines et une journalisation par requête interceptent l’exfiltration qu’aucune vérification de permission ne détecte.


Ce que vous pouvez implémenter dès aujourd’hui

Trois hooks qui traitent les modes d’échec les plus critiques :

1. Classification des sources d’entrée (traite Clinejection). Avant que l’agent ne traite toute entrée externe, classifiez son niveau de confiance. Les titres d’issues d’utilisateurs anonymes ne sont pas fiables. Le code du dépôt est fiable. Les réponses API sont semi-fiables. La classification détermine quels outils l’agent peut utiliser lors du traitement de cette entrée. Les entrées non fiables obtiennent un accès Read-only. Les entrées fiables obtiennent l’ensemble complet des permissions.

2. Refus au niveau du noyau sur le système de fichiers (traite l’évasion de sandbox). Encapsulez chaque appel d’outil Bash dans sandbox-exec (macOS) ou un profil seccomp (Linux). Refusez l’accès aux chemins d’identifiants (~/.ssh, ~/.aws, ~/.gnupg, .env). La surcharge est négligeable (2 ms) et la protection est absolue : l’agent ne peut pas accéder aux chemins refusés quels que soient la commande shell qu’il construit, les sous-processus qu’il engendre ou les alias de chemins qu’il découvre.7

3. Liste d’autorisation des domaines sortants (traite l’exfiltration silencieuse). Avant chaque requête HTTP sortante, vérifiez la destination contre une liste de domaines approuvés. Journalisez toutes les requêtes, approuvées ou refusées. Le journal crée une piste d’audit ; la liste d’autorisation empêche l’exfiltration vers des points de terminaison contrôlés par l’attaquant. Une liste d’autorisation de 12 domaines couvre les services dont un agent de programmation a légitimement besoin (GitHub, npm, PyPI, sites de documentation). Tout ce qui se trouve en dehors de la liste est suspect par défaut.5

Chaque hook fait entre 10 et 30 lignes de script shell. Chacun se déclenche automatiquement à chaque appel d’outil pertinent. Ensemble, ils traitent les trois classes d’attaques démontrées en 2026 : injection de prompt via des entrées non fiables, évasion de sandbox via la manipulation de chemins, et exfiltration de données via des requêtes sortantes autorisées.

L’attaquant de Cline n’a eu besoin que d’une issue GitHub et de trois heures. La prochaine attaque utilisera le même scénario contre un dépôt qui exécute un triage par IA avec des permissions par défaut, des caches partagés et aucune surveillance du trafic sortant. La question n’est pas de savoir si votre sandbox tiendra. Trois efforts de recherche indépendants en 2026 ont prouvé qu’elle ne tiendra pas. La question est de savoir ce qui intercepte l’attaque quand la sandbox échoue.


FAQ

En quoi Clinejection diffère-t-il d’une attaque classique de la chaîne d’approvisionnement ?

Les attaques classiques de la chaîne d’approvisionnement compromettent la machine ou les identifiants d’un développeur. Clinejection a compromis le pipeline CI via l’agent IA qui traite les entrées non fiables des utilisateurs. L’attaquant n’a jamais eu accès au dépôt, n’a jamais compromis d’identifiants et n’a jamais exploité de vulnérabilité dans le système de build. L’attaque a utilisé l’agent IA comme pont entre une entrée non fiable (titre d’issue) et une infrastructure de confiance (pipeline de publication) via le cache partagé.1

Cela signifie-t-il que le triage d’issues par IA est intrinsèquement dangereux ?

Pas intrinsèquement, mais les configurations par défaut actuelles sont dangereuses. Exécuter Claude Code avec un accès Bash sur chaque issue ouverte par n’importe quel utilisateur revient à exécuter du code arbitraire de contributeurs anonymes. Les agents de triage ont besoin d’un accès Read aux métadonnées de l’issue et d’un accès Write pour ajouter des labels. Ils n’ont pas besoin de Bash, web-fetch, ni d’aucun outil capable de modifier l’environnement de build.1

Qu’en est-il des conteneurs et des machines virtuelles pour le sandboxing ?

Les conteneurs et les machines virtuelles offrent une isolation plus forte que les sandboxes au niveau processus, mais ils introduisent de la latence (100 ms+ au démarrage à froid) et de la complexité (gestion des images, montage de volumes, configuration réseau). Pour des sessions d’agents interactives invoquant plus de 50 outils par session, la latence s’accumule. L’approche au niveau du noyau (Seatbelt, seccomp, Veto) fournit l’application sans la surcharge car elle opère dans le modèle de processus existant.7

Un agent peut-il contourner Seatbelt ?

Seatbelt est un framework de contrôle d’accès obligatoire appliqué par le noyau macOS. Le contourner nécessite un exploit du noyau. L’agent s’exécute en espace utilisateur. Il ne peut pas modifier l’état du noyau. Cependant, Seatbelt a une portée plus étroite qu’un conteneur complet : il restreint l’accès aux fichiers et l’exécution des processus mais ne restreint pas l’accès réseau au même degré. Combiner Seatbelt avec un moniteur de trafic sortant couvre les deux surfaces.7

Quel est le rapport avec le cadre de sécurité des agents IA du NIST ?

Mon commentaire public au NIST soutenait que les menaces des agents sont comportementales, pas architecturales. Les échecs de sandbox documentés ici renforcent cet argument : les évasions d’agents sont comportementales (l’agent raisonne sur le contournement des contraintes) et l’attaque la plus dommageable (Clinejection) est entièrement comportementale (des actions autorisées composées en résultats non autorisés). Les cadres existants du NIST (CSF 2.0, SP 800-53, AI RMF) ne traitent pas la composition comportementale comme une classe de menace.9



  1. Khan, A. “Clinejection: Compromising Cline’s Production Releases just by Prompting an Issue Triager.” March 2026. Via Simon Willison

  2. tomvault. “How Claude Code Escapes Its Own Denylist and Sandbox.” ona.com, March 2026. HN discussion, 34 points, 14 comments. 

  3. Jiang, M. et al. “SoK: Organizing, Orchestrating, and Benchmarking Agent Skills at Scale.” Semantic Scholar, February 2026. 

  4. Crosley, B. “The Fabrication Firewall: When Your Agent Publishes Lies.” blakecrosley.com, February 2026. 

  5. Lan, J. et al. “Silent Egress: The Implicit Prompt Injection Attack Surface.” Semantic Scholar, February 2026. Crosley, B. “Silent Egress: The Attack Surface You Didn’t Build.” blakecrosley.com, March 2026. 

  6. dzervas. “mcp-firewall: A tool policy manager for AI agents.” GitHub, March 2026. 

  7. Author’s production hook system. 84 hooks across 15 event types, 60+ sessions. Sandbox: macOS Seatbelt profile, 31 tests, approximately 2ms overhead per command. 

  8. Crosley, B. “The Invisible Agent: Why You Can’t Govern What You Can’t See.” blakecrosley.com, March 2026. 

  9. Crosley, B. “What I Told NIST About AI Agent Security.” blakecrosley.com, February 2026. NIST docket NIST-2025-0035. 

Articles connexes

Silent Egress: The Attack Surface You Didn't Build

A malicious web page injected instructions into URL metadata. The agent fetched it, read the poison, and exfiltrated the…

16 min de lecture

The Invisible Agent: Why You Can't Govern What You Can't See

Anthropic silently dropped a 10GB VM on users' Macs. Agent observability requires three layers: resource metering, polic…

17 min de lecture

Your Agent Writes Faster Than You Can Read

Five research groups published about the same problem this week: AI agents produce code faster than developers can under…

16 min de lecture