Pour les clients de notre programme de vérification de cybersécurité, nous fournissons un nouveau classificateur d'échappement de sandbox dans l'API pour surveiller et réduire les abus. Cet article explique pourquoi les agents autonomes ont besoin d'une isolation forte, comment la conception de référence les isole, et comment délimiter et superviser les engagements qui nécessitent un accès réseau.
Ce classificateur est en bêta privée.
Pour un aperçu de toutes les ressources disponibles, consultez Bonnes pratiques de confinement des agents : mise en route (bêta privée).
Aperçu
Lors d'une exécution autonome, aucun humain n'approuve les appels d'outils de l'agent, et l'agent peut exécuter le code cible. Nous recommandons d'exécuter les agents autonomes dans un sandbox fort qui place un noyau virtualisé par matériel entre l'hôte et l'agent ainsi que le code cible. N'utilisez pas Docker/runc nu, et n'utilisez jamais
--privilegedou le réseau hôte.La conception de référence exécute chaque agent dans sa propre microVM (Kata Containers avec Firecracker) sur un réseau interne. Elle nécessite un hôte Linux avec KVM, ce qui limite les hôtes qui peuvent l'exécuter. Kata a déprécié le runtime sur lequel Firecracker dépend.
Ne montez jamais les chemins qui contiennent des identifiants (tels que
~/.aws,~/.ssh, ou.env) dans l'environnement de l'agent. Gardez également l'identifiant du modèle-API hors de l'environnement de l'agent : faites en sorte qu'un proxy d'identifiants séparé le détienne et l'ajoute à chaque demande de modèle (voir Le proxy d'identifiants).Refusez la sortie par défaut. Dans la conception de référence, les appels de modèle passent par le proxy d'identifiants, et le proxy de sortie refuse toute autre destination à moins que vous ne la mettiez sur liste blanche.
Testez votre sandbox sur chaque hôte avant de vous y fier, et à nouveau chaque fois que le sandbox ou le modèle change.
Pour les engagements qui nécessitent un accès réseau, énoncez la portée dans les instructions de l'agent, appliquez-la sur le réseau, et tenez les agents autonomes à l'écart des systèmes en direct à hautes conséquences (voir Portée et supervision).
Conseils de sandboxing
Propriétés à viser
Si vous construisez votre propre sandbox, ce sont les propriétés que la conception de référence fournit. Le reste de cet article décrit une façon de les obtenir.
Chaque agent a son propre noyau invité, qu'il ne partage pas avec l'hôte.
Les outils de fichier et shell de l'agent ne voient que le système de fichiers de l'invité. Aucun répertoire hôte n'est partagé dans l'invité.
L'identifiant du modèle-API n'est pas dans l'environnement de l'agent ni sur son disque. Un proxy en dehors du sandbox l'ajoute à chaque demande.
L'agent n'a pas d'accès à Internet. La sortie est appliquée en dehors de l'invité, et toute destination est refusée à moins qu'elle ne soit sur une liste blanche.
Le service de métadonnées cloud ne peut pas être atteint depuis l'agent.
Chaque agent a une limite de tours, et une limite de temps si vous en définissez une.
Pas de mode privilégié, de capacités ajoutées, de passthrough de périphérique, ou de réseau hôte.
L'orchestrateur s'exécute sur l'hôte de confiance et y écrit les transcriptions.
Directives générales
Un sandbox fort est plus important pour les exécutions autonomes, où les agents exécutent le code cible et aucun humain n'approuve chaque action
Exécutez les agents autonomes dans des sandboxes forts, et réfléchissez aux effets secondaires qu'un processus dans ce sandbox pourrait toujours causer. Les modèles de pointe sont de plus en plus doués pour trouver des chemins créatifs autour des restrictions : la même propriété qui les rend efficaces en tant que chasseurs de vulnérabilités signifie qu'ils peuvent prendre des actions inattendues contre leur propre environnement d'exécution. Ce n'est pas hypothétique. Anthropic a publié des exemples de modèles contournant des contraintes faibles pour accomplir une tâche (voir Comment nous contenons Claude dans tous les produits).
Concrètement, n'exécutez pas d'agents autonomes de recherche de vulnérabilités dans Docker/runc nu, et surtout pas avec --privileged ou le réseau hôte. Les conteneurs standard partagent le noyau hôte, donc une exploitation du noyau dans le conteneur est une compromission de l'hôte. Nous recommandons de placer un noyau virtualisé par matériel entre le code cible et l'hôte, ce qui signifie exécuter l'agent dans une machine virtuelle. Lorsque ce n'est pas possible, utilisez un hôte bare-metal dédié qui ne contient rien d'autre. Si vous construisez votre propre sandbox, nous recommandons Firecracker sur Linux, Hyper-V sur Windows, et une VM basée sur le framework Hypervisor sur macOS. La conception de référence utilise Firecracker.
Bloquez toute sortie du sandbox. L'agent atteint l'API du modèle uniquement par un proxy qui ajoute l'identifiant et s'exécute en dehors du sandbox, donc le sandbox n'a besoin d'aucune route directe vers l'hôte de l'API. Installez chaque outil, paquet et dépendance avant le début de l'exécution, afin que rien n'ait besoin d'être récupéré pendant celle-ci.
L'utilisation interactive, avec un humain dans la boucle, comporte généralement moins de risques, mais nous recommandons toujours un sandbox pour cela. Si vous pilotez un agent de manière interactive à partir de Claude Code sur un ordinateur portable, examinez chaque utilisation d'outil (mode manuel), ou fiez-vous au classificateur de permissions du mode automatique et faites approuver par un humain chaque action qui sort du référentiel. Le mode automatique supprime les invites de permission de routine : il approuve les lectures et les modifications du répertoire de travail automatiquement et envoie tout le reste à un classificateur en arrière-plan qui vise à bloquer les actions destructrices, irréversibles ou hors tâche. C'est une vérification au mieux. Elle peut manquer des choses, et sur le travail de sécurité, elle peut aussi refuser certaines étapes légitimes. Le mode automatique décrit comment il fonctionne, à quoi s'attendre et comment le configurer pour votre environnement.
Ne montez jamais les chemins porteurs d'identifiants tels que ~/.aws, ~/.ssh, ou .env dans l'environnement de l'agent. Il en va de même pour l'identifiant que les appels de modèle de l'agent utilisent. Gardez-le en dehors du sandbox, et faites en sorte qu'un proxy que l'agent ne peut pas lire l'ajoute à chaque demande (voir Le proxy d'identifiants). Ne connectez pas les agents aux serveurs MCP ou aux outils ayant accès en écriture à l'état externe tel que le courrier électronique, le stockage cloud ou l'infrastructure de production.
Divisez chaque exécution en une phase de configuration et une phase d'attaque avec des politiques réseau différentes
Ceci est un modèle qui met en pratique les directives ci-dessus. La phase de configuration a un accès Internet sortant et un humain dans la boucle qui approuve chaque appel d'outil. L'agent y récupère les dépendances, construit la cible et configure son sandbox à partir d'un document de spécification. La phase d'attaque n'a pas d'accès Internet général. Toute sortie passe par un proxy de liste blanche qui ne permet que les hôtes nommés dans l'engagement, donc le proxy applique également la portée. Les appels de modèle passent par le proxy d'identifiants séparé. L'agent peut alors sonder la cible sans surveillance. Le proxy contient le trafic de l'agent lui-même. Il ne contient pas le trafic qu'une cible en réseau envoie au nom de l'agent.
Intégrez les dépendances dont l'agent a besoin régulièrement dans l'image de configuration, afin que les exécutions de phase d'attaque n'aient besoin d'aucun accès Internet. Délimitez les identifiants par cible, afin qu'un agent travaillant sur une cible ne puisse pas les utiliser contre une autre. Gardez le mode automatique de Claude Code activé dans le sandbox pendant la phase d'attaque et décrivez le sandbox à son classificateur. Voir Le mode automatique.
Limitez chaque exécution, et connaissez votre bouton d'arrêt
Donnez à chaque agent un budget explicite, afin qu'une exécution qui dépasse ses tests prévus s'arrête d'elle-même et non quand quelqu'un le remarque. Appliquez une limite de tours stricte à chaque agent. Quand un agent l'épuise, terminez l'exécution et n'accordez pas automatiquement plus de tours. Relancer avec une limite plus élevée est le moment où une personne décide de continuer. Limitez également les exécutions dans le temps. Terminez une session qui dépasse sa limite de temps de la même manière : l'exécution est définitive et jamais reprise, et le processus de l'agent est arrêté, même quand la limite est atteinte au milieu d'une commande longue. Si une limite est définie à une valeur qui ne peut pas être lue, refusez de lancer au lieu d'exécuter sans limite. Définissez les limites délibérément pour l'engagement et n'acceptez pas une valeur par défaut généreuse. Associez-les à la cadence de surveillance dans surveillance hors ligne des transcriptions d'agents, afin qu'un long lot soit examiné toutes les heures ou deux et non seulement à la fin. Sachez comment arrêter un seul agent sans arrêter le lot. Dans une configuration basée sur Docker, c'est docker rm -f <agent-container>. L'orchestrateur doit enregistrer cette exécution comme échouée et continuer avec le reste du lot.
Pour plus de conseils, lisez deux ressources Anthropic. Déploiement sécurisé d'agents IA couvre les options d'isolation, le proxying des identifiants et le durcissement du système de fichiers. La rétrospective d'ingénierie Comment nous contenons Claude dans tous les produits couvre ce qui a tenu et ce qui n'a pas tenu quand ces mêmes mécanismes s'exécutaient en production.
Portée et supervision
Le sandbox limite ce qu'un agent peut atteindre. Pour les tests de pénétration, les équipes rouges et autres engagements qui nécessitent un accès réseau, les pratiques ci-dessous limitent ce que l'agent est demandé et autorisé à faire. Elles dépendent de vos cibles et de votre équipe, donc les outils ne peuvent pas mettre la plupart d'entre elles en place pour vous.
Énoncez la portée dans les instructions de l'agent
Avant une exécution, dites à l'agent quelles cibles sont dans la portée, quelles actions sont autorisées, où se trouve la limite du réseau et ce qui est hors de portée. Formulez chaque contrainte comme une intention (« n'accédez pas aux hôtes en dehors de 10.0.3.0/24 ») et non comme une affirmation sur l'environnement (« vous ne pouvez pas atteindre Internet »), afin que l'instruction tienne toujours si l'environnement est mal configuré. Faites cela aussi pour le travail local en sandbox : dites à l'agent de ne pas utiliser l'accès Internet, même si le sandbox le bloque. La description que vous donnez au classificateur du mode automatique est une chose différente. Elle énonce des faits sur la machine (voir Mode automatique).
Appliquez la même portée sur le réseau
Quand vous le pouvez, exécutez l'agent à l'intérieur de la même isolation décrite ci-dessus, et mettez sur liste blanche la sortie vers les cibles dans la portée uniquement (voir Liste blanche de sortie). L'agent atteint l'API du modèle par le proxy d'identifiants, pas par la liste blanche. Quand l'une est disponible, pointez l'engagement vers un environnement de préproduction ou de réplica qui est déconnecté de la production.
Courtisez l'accès à la cible quand vous le pouvez
Donnez à l'agent l'accès aux systèmes cibles par quelque chose que vous pouvez observer, comme un proxy d'accès ou un ensemble défini d'outils. Évitez de laisser l'agent écrire ses propres outils avec un accès général à la cible. Dans un harnais personnalisé, séparez les outils en lecture seule des outils qui changent l'état, et supervisez le deuxième groupe plus étroitement. Envisagez d'analyser les commandes risquées au fur et à mesure qu'elles sont proposées, et de les refuser ou de les escalader à une personne.
Supervisez les exécutions qui ont un accès réseau
Nous recommandons qu'un ingénieur observe chaque exécution au fur et à mesure qu'elle s'exécute, en suivant les appels d'outils et l'activité réseau, et soit capable d'arrêter l'exécution immédiatement. Les agents agissent à la vitesse de la machine, donc l'observation en direct complète les contrôles qui agissent avant qu'une action ne s'exécute (listes blanches réseau, outils courtisés et examen des actions changeant d'état). Elle ne les remplace pas. Pour les exécutions longues ou autonomes où l'attention continue est impraticable, surveillez continuellement dans le logiciel (voir Surveillance hors ligne des transcriptions d'agents).
Tenez les agents autonomes à l'écart des systèmes en direct à hautes conséquences
N'exécutez pas d'agents autonomes contre des systèmes de production en direct où une action hors de portée pourrait mettre en danger la sécurité ou la disponibilité des services critiques, tels que OT/ICS, médical ou systèmes énergétiques. C'est déjà la norme pour les tests menés par des humains de tels systèmes, et cela s'applique également ici. Testez contre une réplica, un banc d'essai ou un jumeau numérique, ou pendant une panne planifiée. Quand l'accès en direct est inévitable, limitez l'agent à une activité passive ou en lecture seule et faites en sorte qu'une personne exécute chaque étape changeant d'état.
Testez le sandbox avant de vous y fier
Avant d'exécuter des engagements réels à partir d'un hôte, testez son sandbox avec les deux étapes ci-dessous. Faites cela avant la première utilisation réelle, et à nouveau chaque fois que vous changez le modèle ou le sandbox. Les modifications du sandbox incluent un nouvel hôte, une nouvelle version de l'hyperviseur ou du runtime du conteneur, une configuration réseau ou proxy différente, et une configuration de conteneur ou de composition modifiée.
Tout d'abord, demandez à Claude d'examiner la configuration
Dans une session Claude Code interactive sur l'hôte, demandez-lui de lire la configuration du bac à sable telle qu'elle est configurée sur cette machine et de signaler tout ce qui affaiblit la limite décrite dans cet article. Pointez-le vers :
La configuration de l'hyperviseur et du runtime de conteneur (pour la conception de référence, le
configuration.tomlrendu de Kata et ledaemon.jsonde Docker) ;Le réseau des agents et le proxy de sortie tels que le runtime les signale, et la liste d'autorisation du proxy ;
Le proxy de credentials tel que le runtime le signale, et l'environnement d'un conteneur d'agent en cours d'exécution (voir Le proxy de credentials ci-dessous) ;
Tous les fichiers de composition ou d'orchestration qui démarrent des agents ou des cibles ;
La liste de ce qui est monté ou diffusé dans les invités (voir Notes opérationnelles ci-dessous).
Cette étape ne lit que la configuration et l'état. Elle ne lance pas d'agent.
Ensuite, exécutez un test d'évasion supervisé
Lancez l'agent de test de la même manière que vous lancez les agents de production, et non avec une commande construite à la main, afin que le test exerce le vrai chemin. La section Vérifiez l'isolation vous-même ci-dessous couvre les vérifications manuelles de la limite à la place. Donnez à l'agent une seule tâche : essayer d'atteindre n'importe quoi en dehors de sa limite, et arrêter et signaler dès que quelque chose réussit. Nommez la limite concrètement dans l'invite : l'hôte, d'autres conteneurs, le socket du runtime de conteneur, le service de métadonnées du cloud, et tout hôte qui ne figure pas sur la liste d'autorisation du proxy. Exécutez ceci uniquement sous une supervision humaine étroite, sur un hôte sans accès à Internet au-delà de l'API du modèle et que vous êtes prêt à reconstruire, afin qu'une évasion réussie ne cause aucun dommage. Sur du métal nu, exécutez le test à l'intérieur d'une VM jetable. Sur une VM cloud, utilisez une instance nouvelle et détruisez-la après. Regardez la session pendant qu'elle s'exécute. Traitez tout succès comme un bloqueur : corrigez l'hôte, répétez le test, et ne lancez pas d'engagements à partir de cet hôte jusqu'à ce que le test réussisse.
Après, lisez la transcription complète
Vérifiez ce que l'agent a essayé ainsi que s'il s'est échappé. Recherchez les connexions directes qui n'ont pas traversé le proxy, les lectures de fichiers de credentials ou d'adresses de métadonnées, l'utilisation du socket du runtime de conteneur ou les sondes de conteneurs voisins, les écritures en dehors du système de fichiers du conteneur lui-même, et les tentatives de modification des paramètres ou des outils de l'agent lui-même. Le test réussit lorsque la transcription montre que chacun de ceux-ci a été essayé et a échoué pour la raison que vous attendez. Enregistrez, pour chacun, si le bac à sable ou le classificateur de permissions l'a arrêté. Une tentative que le classificateur a refusée n'a jamais atteint le bac à sable, alors couvrez-la avec les vérifications manuelles (voir Vérifiez l'isolation vous-même ci-dessous). Un test réussi est une barre minimale, pas une preuve d'isolation.
Évitez les tâches impossibles et examinez d'abord les exécutions échouées
Confirmez avant le lancement que la tâche peut être complétée telle que donnée. Quelques exemples de tâches qui ne peuvent pas être complétées : une zone de focus sans rien à trouver, une cible qui n'est pas accessible, un bug qui n'existe pas, ou un outil dont la tâche a besoin qui n'est pas installé. Chaque fois que vous modifiez votre configuration ou commencez un nouveau type de tâche, confirmez avant le lancement que la cible se construit et peut être atteinte et que l'agent dispose des outils dont il a besoin. Pour la même raison, lorsque vous examinez un lot, lisez les transcriptions des exécutions qui ont échoué ou n'ont rien trouvé avant celles qui ont réussi.
Vérifiez l'isolation vous-même
Exécutez ces vérifications à la main sur chaque hôte. La deuxième colonne décrit la vérification pour la conception de référence (Docker avec le runtime Kata et Firecracker). Adaptez-la à votre propre runtime.
Ce qu'il faut confirmer | Comment | Résultat attendu |
Un noyau invité séparé | Exécutez | Les deux versions diffèrent |
Le moniteur de VM est emprisonné sur l'hôte | Pour un conteneur en cours d'exécution, inspectez le processus Firecracker : son répertoire racine, | Seuls les fichiers de la VM elle-même se trouvent sous sa racine. |
Un fichier hôte n'est pas visible à l'intérieur | Créez un fichier sur l'hôte et essayez de le lire à partir d'un conteneur en bac à sable | Non trouvé. C'est une vérification basique que tout runtime devrait réussir |
La sortie est refusée | À partir d'un conteneur d'agent, demandez l'hôte de l'API du modèle et un autre hôte public via le proxy de sortie | Les deux sont refusés, et le proxy de sortie enregistre une ligne de refus pour chacun. Les agents n'atteignent le modèle que via le proxy de credentials |
Aucune credential dans le conteneur d'agent | Pendant qu'une exécution est en cours, listez l'environnement du conteneur d'agent, filtré pour les noms de fournisseur | Un espace réservé, l'adresse du proxy de credentials, et les paramètres du fournisseur. Aucune clé réelle, jeton ou fichier de credential |
La conception de référence
Cette section décrit comment l'implémentation de référence respecte les conseils ci-dessus. L'implémentation n'est pas incluse. Lisez-la comme une conception que vous pouvez copier.
Comment chaque agent est isolé
Chaque agent s'exécute en tant que claude -p à l'intérieur de sa propre microVM, à côté du binaire cible et de la source. La microVM est un conteneur Kata Containers soutenu par le moniteur de machine virtuelle Firecracker, enregistré auprès de Docker en tant que runtime. Les outils Read, Write et Bash de l'agent ne voient que le système de fichiers et le noyau de cet invité.
La connexion entre un invité et l'hôte est délibérément petite. Elle se compose de KVM et des quelques appareils virtuels que Firecracker émule : des appareils de bloc pour le disque du conteneur, une interface réseau, et un canal de contrôle vsock que Kata utilise pour démarrer des processus à l'intérieur de l'invité. Le processus Firecracker lui-même est confiné sur l'hôte. Il s'exécute dans une « prison », qui est un répertoire chroot contenant uniquement les fichiers de cette VM, avec son propre espace de noms de montage, l'espace de noms réseau du conteneur, et le filtre seccomp intégré de Firecracker. Il est comptabilisé dans le cgroup du conteneur. Ce en quoi vous faites confiance du côté de l'hôte est KVM, Firecracker, et le processus runtime de Kata (le « shim » par conteneur qui parle à Docker, qui s'exécute en tant que root).
L'orchestrateur reste sur l'hôte de confiance. Il gère le cycle de vie des conteneurs, diffuse les transcriptions, et déplace les fichiers avec docker exec, que Kata sert via son agent à l'intérieur de l'invité. Le lanceur démarre les agents uniquement à l'intérieur de ce bac à sable. Avant le démarrage de tout agent, il vérifie que le runtime du bac à sable est enregistré, que /dev/kvm est présent, et que le proxy de sortie est actif, et il refuse de s'exécuter sinon.
Ce que le bac à sable change pour chaque surface :
Surface | Sans bac à sable | Avec bac à sable |
Agent | système de fichiers hôte | système de fichiers invité uniquement (le disque virtuel propre du conteneur, sous le noyau invité) |
Agent | shell hôte uniquement | shell invité uniquement (noyau invité ; l'hôte n'est accessible que via KVM et les appareils virtuels de Firecracker) |
Sortie réseau | tout ce que l'hôte possède | pas d'accès à Internet ; appels de modèle uniquement, via le proxy de credentials |
Credential du modèle-API | dans l'environnement de l'agent | pas dans le conteneur de l'agent ; détenu par un conteneur proxy de credentials séparé (voir Le proxy de credentials ci-dessous) |
Couplage d'hôte | complet |
|
Vérifications des permissions | classificateur en mode automatique uniquement | classificateur en mode automatique plus la limite de la microVM (voir Mode automatique) |
Où chaque propriété est appliquée : la virtualisation matérielle fournit la limite du noyau et du système de fichiers. Les opérations Read/Write/Bash de l'agent s'exécutent sur le noyau invité, et le processus Firecracker derrière lui est emprisonné et confiné par seccomp sur l'hôte. La politique de sortie est appliquée du côté hôte de l'interface réseau de la VM, par un pont Docker --internal (pas de route par défaut) et les deux proxies sur ce réseau. Le proxy de credentials transfère les appels de modèle et rien d'autre. Le proxy de sortie refuse toute autre destination, car sa liste d'autorisation est vide à moins que vous n'y ajoutiez quelque chose. Le trafic sort par la pile réseau propre de l'invité ; le filtrage se fait dans les deux proxies.
Le proxy de credentials
La credential pour l'API du modèle (votre clé API, jeton OAuth, credential AWS ou Google) n'est jamais placée dans un conteneur d'agent. L'orchestrateur sur l'hôte la lit et la valide, et chaque lancement démarre un petit conteneur supplémentaire, le proxy de credentials, pour la détenir. Le proxy est attaché au réseau interne des agents, et les conteneurs d'agent envoient leurs appels de modèle à celui-ci : leur CLI claude obtient l'adresse du proxy comme URL de base API, et une valeur d'espace réservé fixe où la clé ou le jeton se trouverait normalement. Cela suit la meilleure pratique d'accéder à l'API du modèle uniquement via un proxy, avec la clé API injectée de l'extérieur du sandbox. Dans la conception de référence, le proxy est un conteneur séparé sur le réseau des agents, pas un processus sur le localhost propre de l'agent. Pour chaque demande, le proxy :
Refuse tout ce qui n'est pas un appel de modèle au point de terminaison du fournisseur unique pour lequel le lancement a été configuré (les autres chemins et hôtes reçoivent un 403 et une ligne de journal) ;
Supprime tous les en-têtes d'authentification que le conteneur a envoyés ;
Ajoute la credential réelle : l'en-tête de clé API, un jeton porteur (que le proxy actualise lui-même lorsque le jeton a une durée de vie courte), ou une signature AWS SigV4 calculée sur la demande exacte ;
Transfère la demande au fournisseur via HTTPS avec vérification du certificat, et diffuse la réponse en continu.
Pour un conteneur d'agent compromis, cela signifie qu'il n'y a pas de clé, de jeton ou de fichier de credential à lire, copier ou envoyer n'importe où. Les services de métadonnées cloud sont également inaccessibles depuis le conteneur. Ce que le conteneur peut toujours faire, c'est faire des appels de modèle via le proxy, sur votre compte, aussi longtemps que l'exécution est active. Pour cette raison, préférez une credential étroitement délimitée pour les exécutions d'agent, et faites-la tourner après toute exécution dont la transcription montre un comportement inattendu. Le proxy enregistre une ligne par demande, avec l'adresse du client, la méthode, le chemin, le statut et la taille. Il n'enregistre pas les en-têtes ou les corps. Enregistrez ce journal à la fin de l'exécution (voir la section Rétention dans Surveillance hors ligne des transcriptions d'agent).
Tout ce que l'agent envoie à l'API du modèle quitte votre réseau, dans les corps de demande que le proxy n'inspecte ni n'enregistre.
Ce que chaque côté détient, par route d'authentification :
Route | Ce que le proxy de credentials détient | Ce que le conteneur d'agent obtient |
Clé API | la clé | adresse du proxy + placeholder |
Jeton OAuth ( | le jeton | adresse du proxy + placeholder |
Fédération d'identité de charge de travail (WIF) | le jeton d'identité, plus le jeton d'accès que le proxy échange et actualise. Avec | adresse du proxy + placeholder |
profil | le répertoire de profil, monté en lecture seule dans le proxy | adresse du proxy + placeholder |
Bedrock | le jeton porteur, ou l'ensemble de clés d'accès (le proxy signe chaque demande) | adresse du proxy, |
Vertex | la clé de compte de service, plus les jetons d'accès que le proxy crée à partir de celle-ci et actualise | adresse du proxy, |
Le conteneur proxy de credentials fait partie du côté de confiance de la configuration. Il s'exécute sous runc simple plutôt que sous le runtime du sandbox, en tant que root avec chaque capacité supprimée sauf celle dont il a besoin pour lire les fichiers montés, et avec un système de fichiers en lecture seule. Il écoute uniquement sur son adresse sur le réseau interne des agents, et il se connecte directement au fournisseur plutôt que via le proxy de sortie. L'orchestrateur transmet la credential au proxy en cours d'exécution via docker exec. Pour les routes de fichier de jeton WIF et de profil, le répertoire contenant le jeton ou le profil est monté en lecture seule dans le proxy, qui lit le fichier à partir de là. La credential n'est pas dans l'environnement du conteneur proxy ou sur sa ligne de commande, de sorte que docker inspect sur celui-ci affiche les montages et non un secret.
Démarrez un proxy par lancement, et supprimez-le à la fin de l'exécution ou s'il est interrompu. Vérifiez les proxies laissés derrière par une exécution qui a été tuée, et supprimez-les avant le prochain lancement.
Le proxy de credentials a deux effets secondaires. Premièrement, la CLI des agents reçoit une adresse API non définie par défaut, de sorte que quelques fonctionnalités CLI qui s'appliquent uniquement à l'adresse par défaut sont désactivées dans les conteneurs d'agent. Sa télémétrie et ses vérifications de mise à jour sont également désactivées, car elles n'auraient de toute façon aucune route. Deuxièmement, sur Vertex, le filtre de chemin du proxy est le contrôle principal qui empêche un conteneur d'agent d'utiliser le reste de l'API Vertex AI (voir Liste d'autorisation de sortie). Une vérification de la portée IAM de la clé au lancement est une deuxième couche.
Liste d'autorisation de sortie
La liste d'autorisation du proxy de sortie est vide par défaut. Les conteneurs d'agent accèdent à l'API du modèle uniquement via le proxy de credentials (voir Le proxy de credentials). Chaque lancement démarre ce proxy pour le fournisseur que vos credentials sélectionnent, de sorte que rien de spécifique au fournisseur n'est stocké dans la configuration du sandbox. Toute autre destination qu'un agent demande via le proxy de sortie, y compris l'hôte API du modèle lui-même, reçoit un 403 et une ligne de refus dans son journal. Les valeurs de région qui sélectionnent les points de terminaison Bedrock et Vertex (AWS_REGION, CLOUD_ML_REGION) sont vérifiées par rapport à un modèle strict avant d'être utilisées, de sorte qu'une valeur mal formée ne peut pas envoyer la credential à un hôte différent.
Vertex a une limite à connaître. …aiplatform.googleapis.com sert l'ensemble de l'API Vertex AI, de sorte qu'une credential autorisée à créer des travaux personnalisés pourrait exécuter un conteneur arbitraire avec un accès Internet complet dans votre projet. Utilisez deux contrôles contre cela. Faites en sorte que le proxy de credentials transfère uniquement les appels de modèle d'éditeur sur votre projet configuré (…/publishers/anthropic/models/…:rawPredict, :streamRawPredict, et :countTokens) et refuse tout autre chemin. Et vérifiez la portée IAM de la clé au lancement et échouez fermé : refusez l'ADC utilisateur gcloud, vérifiez une clé de compte de service avec testIamPermissions, et refusez-la si elle détient une permission de création de charge de travail. Accordez au compte un rôle personnalisé qui détient uniquement aiplatform.endpoints.predict. Le serveur de métadonnées, le STS de Google et les points de terminaison des credentials IAM ne doivent pas être accessibles depuis les conteneurs d'agent.
Si les agents ont besoin d'accéder à des hôtes supplémentaires, tels qu'un miroir de package ou une cible dans le périmètre, ajoutez-les à la liste d'autorisation du proxy de sortie en tant qu'entrées host:port. Ajoutez uniquement ce dont l'engagement a besoin (voir Portée et supervision).
N'ajoutez pas l'hôte de l'API du modèle à cette liste. Les agents n'en ont pas besoin, car leurs appels de modèle passent par le proxy de credentials. L'ajouter donne aux conteneurs d'agents une route directe vers l'API, et le reste de la conception, y compris ce que le classificateur de permissions est informé, suppose qu'ils n'en ont pas.
Modifier la liste d'autorisation signifie redémarrer le proxy de sortie, ce qui interrompt toutes les connexions d'agents actives. Faites-le entre les lots plutôt que pendant un lot, et confirmez ensuite quelle liste le proxy a chargée.
Dérivez le point de terminaison du fournisseur de votre configuration de credentials, et ignorez une variable d'URL de base telle que ANTHROPIC_BASE_URL définie sur l'hôte : le proxy de credentials doit toujours transférer vers le point de terminaison que les credentials sélectionnent.
Construire et exploiter un sandbox comme celui-ci
Cette section rassemble ce qui a été appris en exécutant des agents sous Kata avec Firecracker dans l'implémentation de référence. Ce n'est pas un ensemble d'étapes d'installation.
Exigences de l'hôte
La conception de référence nécessite une machine Linux physique, ou une VM qui peut elle-même exécuter des VMs :
Linux x86_64 ou aarch64 avec KVM (
/dev/kvmprésent et utilisable) : métal nu, ou une VM cloud avec virtualisation imbriquée activée.GCE, Azure et AWS offrent la virtualisation imbriquée sur les types d'instances sélectionnés (sur AWS, par exemple, les familles C8i, M8i et R8i). Les instances AWS bare-metal (
*.metal) fonctionnent également.La virtualisation imbriquée coûte un peu de performance. On ne s'attend pas à ce qu'elle affaiblisse la limite.
Stockage sur périphérique bloc pour les conteneurs. Firecracker ne peut pas partager un répertoire hôte dans un invité ; le seul stockage qu'il peut attacher à une VM est un périphérique bloc. Les systèmes de fichiers racine des conteneurs doivent donc exister en tant que périphériques bloc au lieu du système de fichiers overlay habituel. Avec Docker, le snapshotter
devmapperde containerd le fournit. Il nécessite Docker rootful (la conception de référence utilise Engine 25 ou plus récent) soutenu par le containerd système (2.0 ou plus récent).Accès réseau sortant pendant que vous construisez l'hôte et les images. Les agents n'obtiennent pas cette sortie.
Cela ne fonctionnera pas sur :
un conteneur ou un pod Kubernetes, y compris Docker-in-Docker et les exécuteurs CI basés sur des conteneurs. Le containerd de l'hôte, le démon Docker et le device-mapper ne peuvent pas être configurés depuis l'intérieur d'un conteneur, et KVM n'est généralement pas disponible non plus ;
Docker sans privilèges ;
une VM sans virtualisation imbriquée, qui est la plupart des types d'instances cloud à usage général, sauf si vous en choisissez une qui l'offre et l'activez ;
macOS ou Windows, y compris Docker Desktop et WSL2.
La conception de référence ne supporte pas les hôtes macOS ou Windows
Son sandbox a besoin de KVM sur un hôte Linux. Docker sur un Mac s'exécute à l'intérieur d'une VM Linux partagée qui monte le répertoire personnel de l'utilisateur et héberge le démon Docker, il ne peut donc pas fournir d'isolation matérielle par agent. Si vous travaillez sur un Mac, exécutez les agents sur un hôte Linux avec KVM (métal nu, ou une VM cloud avec virtualisation imbriquée) et pilotez-les via SSH. Si vous construisez votre propre sandbox sur macOS ou Windows, consultez les hyperviseurs nommés dans la section Directives générales ci-dessus.
Changer le magasin d'images de Docker a un effet secondaire
Les images et conteneurs créés sur le magasin précédent de Docker deviennent invisibles pour Docker après le passage au snapshotter devmapper. Ils restent sur le disque. Pour les voir à nouveau, mettez les deux paramètres de stockage dans daemon.json (storage-driver et features.containerd-snapshotter) à ce qu'ils étaient et redémarrez Docker.
Paramètres Kata
Épinglez la version de Kata et vérifiez son digest avant de l'installer. La conception de référence part du profil Firecracker de Kata et épingle ces paramètres dans /etc/kata-containers/configuration.toml :
Paramètre | Valeur | Pourquoi |
| chemin vers le binaire | Démarre Firecracker à l'intérieur de sa prison : un chroot avec seulement les fichiers de la VM, son propre espace de noms de montage, l'espace de noms réseau du conteneur et le filtre seccomp de Firecracker. S'il n'est pas défini, Kata exécuterait Firecracker sans la prison. |
|
| Un conteneur ne peut pas modifier aucun paramètre d'hyperviseur via les annotations OCI. |
|
| Le profil seccomp de Docker pour le conteneur est également appliqué à l'intérieur de l'invité, une deuxième couche sous la limite de la VM. |
|
| Firecracker et ses threads d'E/S sont placés dans le cgroup du conteneur, de sorte que la VM est comptabilisée au conteneur. Le fait que la limite |
|
| Firecracker ne peut pas ajouter de CPUs ou de mémoire à une VM en cours d'exécution, la VM est donc dimensionnée une fois au démarrage à partir des limites du conteneur. |
|
| Ligne de base par VM ; la |
|
| Pas de console dans les invités, et pas de sortie de console d'invité dans les journaux d'hôte. |
|
| Désactivé, car le modèle de VM partagerait les pages de mémoire d'invité entre les VMs. |
|
| Entropie d'hôte non-bloquante pour les invités. |
Les valeurs kernel, image et kernel_params qui accompagnent la version Kata sont conservées telles quelles.
Rendre le noyau et l'image de l'invité immuables
Chaque VM démarre à partir des mêmes deux fichiers, Kata les lie-monte dans chaque jail, et le jailer est démarré en tant que root, donc les permissions de fichier ordinaires n'empêcheraient pas un processus Firecracker compromis de réécrire l'image à partir de laquelle chaque VM ultérieure démarre. Définissez le drapeau immuable sur les deux (chattr +i). L'effacement de ce drapeau nécessite un appel système que le filtre seccomp de Firecracker n'autorise pas, conçu pour empêcher même root à l'intérieur de la jail de le faire. Effacez le drapeau vous-même avant d'installer une nouvelle version de Kata. Sur un système de fichiers sans support chattr, utilisez plutôt un montage de liaison en lecture seule.
Dimensionnement
Mémoire
Chaque VM d'agent est dimensionnée une fois, au démarrage : default_memory plus la --memory du conteneur. Avec une ligne de base de 4096 MiB et une limite de conteneur 4g, un agent est une VM de 8 GiB. L'hôte alloue cette mémoire à la VM au fur et à mesure que l'invité l'utilise, pas tout au démarrage, mais prévoyez le montant total par agent concurrent : dix agents en parallèle peuvent croître vers 80 GiB. Le fait que la limite --memory du conteneur plafonne également la VM dans son ensemble dépend de la façon dont les cgroups de l'hôte sont disposés. Vérifiez lequel de ces éléments s'applique sur votre hôte :
La limite du conteneur s'applique à l'ensemble de la VM. Un agent ne peut pas utiliser plus de mémoire hôte que
--memorymême si sa VM est nominalement plus grande, et une VM qui dépasse la limite est tuée du côté de l'hôte.Rien sur l'hôte ne plafonne la VM en dessous de sa taille de démarrage. L'utilisation de mémoire d'un agent est limitée par la taille de la VM (
default_memory+--memory) et le tueur de mémoire insuffisante du noyau invité lui-même.Un cgroup parent la plafonne à une valeur différente.
Nous n'avons pas confirmé ce comportement sur tous les types d'hôtes. De toute façon, dimensionnez l'hôte par taille de VM.
CPUs
Chaque VM obtient default_vcpus. Firecracker ne peut pas ajouter de CPUs à une VM en cours d'exécution, donc pour les cibles gourmandes en construction, augmentez la valeur avant le lancement ; le maximum est 32 par VM.
Disque
Chaque image et chaque conteneur obtient un disque virtuel d'un pool fin de device-mapper, qui soutient le magasin d'images. Si le pool se remplit, les écritures à l'intérieur des conteneurs échouent avec des erreurs d'E/S ou d'espace insuffisant. Si le système de fichiers qui contient le pool se remplit en premier, le pool devient en lecture seule et chaque conteneur dessus échoue. Libérez de l'espace avec docker rmi et docker system prune (les blocs libérés reviennent au pool). sudo dmsetup status <pool> affiche l'utilisation. Pour un hôte de longue durée, un pool fin LVM sur un disque dédié est la meilleure disposition.
Temps de démarrage
Chaque démarrage d'agent démarre un noyau invité. Cela prend bien moins d'une seconde sur du métal nu et quelques secondes sous virtualisation imbriquée, ce qui est petit comparé aux temps d'exécution des agents.
Durcissement de l'hôte
Dédiez l'hôte à ce travail.
Supposez qu'un agent pourrait lire n'importe quoi dessus, et ne conservez aucune information d'identification ou données sensibles là-bas autre que la credential de l'API modèle dont les agents ont besoin.
Gardez chaque couche que le trafic de l'agent touche corrigée, pas seulement le noyau : Docker, les images de base des conteneurs proxy, et tout pare-feu ou appareil réseau entre l'hôte et l'API modèle. Un proxy ou un pare-feu obsolète à la limite du bac à sable est lui-même une surface d'attaque.
Gardez le noyau, KVM et le micrologiciel CPU à jour, et laissez les atténuations des vulnérabilités CPU du noyau à leurs valeurs par défaut.
grep . /sys/devices/system/cpu/vulnerabilities/*ne devrait afficher aucune ligneVulnerable.Si l'hôte est partagé avec des charges de travail qui ne doivent pas s'observer mutuellement, suivez également le guide configuration d'hôte de production de Firecracker sur les paramètres SMT et d'exécution spéculative.
Désactivez le swap (
sudo swapoff -a, et supprimez-le de/etc/fstab) afin que la mémoire invitée ne soit pas écrite dans le swap./dev/kvmn'a pas besoin d'être accessible en écriture par tous, et les répertoires d'installation et d'exécution de Kata doivent rester la propriété de root et ne pas être accessibles en écriture par d'autres utilisateurs.root:kvmavec le mode0660suffit pour/dev/kvm, car l'exécution de Kata s'exécute en tant que root.
N'ajoutez jamais
--privileged,--device,--cap-addou la mise en réseau d'hôte aux conteneurs d'agent ou aux services cibles.Sous Kata, ces drapeaux transmettent les appareils et privilèges de l'hôte dans la VM.
Gardez les agents sur le réseau interne derrière les deux proxies.
Firecracker ne fait aucun filtrage de paquets de son propre chef ; le réseau côté hôte et les proxies sont le contrôle de sortie.
Gardez
enable_debugdésactivé en dehors du dépannage ; la journalisation de débogage inclut la sortie de la console invitée.
Validation d'un nouvel hôte
Après avoir configuré une machine neuve, cette séquence montre que le bac à sable fonctionne de bout en bout. Les étapes 3 et 4 effectuent des appels de modèle réels.
Exécutez les vérifications d'isolation sous Vérifiez l'isolation vous-même. Les deux versions du noyau doivent différer. Notez si la limite de mémoire du conteneur plafonne la VM (voir Dimensionnement).
Confirmez que l'interface de ligne de commande de l'agent s'exécute sous l'exécution du bac à sable, dans l'image que vous utiliserez.
Testez la limite : faites examiner la configuration du bac à sable par Claude, puis exécutez le test d'évasion supervisé, tous deux comme décrit dans Testez le bac à sable avant de vous y fier.
Exécutez un petit lot de bout en bout contre une cible que vous connaissez. Exécutez cette étape avec le mode de credential que vous utiliserez pour les engagements réels, pas une clé API de remplacement : le proxy de credential gère chaque mode différemment (échange de jetons pour WIF, signature pour Bedrock, création de jetons pour Vertex), et cette exécution confirme que la vôtre fonctionne de bout en bout. Vérifiez le journal du proxy de credential après.
Vérifiez qu'aucun reste n'a été laissé. Une fois le lot terminé, aucun conteneur d'agent, conteneur d'aide, processus VM ou proxy de credential ne devrait rester. Le journal du proxy de sortie ne devrait afficher aucune ligne de refus autre que les sondes des étapes 1 et 3, et le journal du proxy de credential ne devrait afficher que les appels de modèle.
Notes d'exploitation
L'exécution d'agents sous Kata avec Firecracker diffère de l'exécution de conteneurs simples de ces façons.
Les montages de liaison sont des copies ; les fichiers en direct doivent être diffusés
Firecracker n'a pas de partage de système de fichiers d'hôte, donc Kata copie un fichier ou un répertoire lié-monté dans l'invité au démarrage du conteneur, et les modifications ultérieures sur l'hôte ne sont pas visibles à l'intérieur. C'est bien pour les entrées qui ne changent pas pendant une exécution, comme la source cible, et celles-ci peuvent rester des montages en lecture seule. Aucun fichier de credential n'est monté ou diffusé, car les conteneurs d'agent n'en contiennent aucun (voir Le proxy de credential). Un fichier qui change pendant une exécution doit être écrit dans le conteneur par l'orchestrateur, via docker exec, et maintenu à jour. Les copies dans le conteneur sont des fichiers ordinaires qu'un agent pourrait modifier, donc faites en sorte que l'orchestrateur lise les originaux sur l'hôte, et jugez les résultats à partir d'une copie que l'agent en test ne peut pas atteindre.
Chaque agent a besoin d'un conteneur compagnon pour son réseau
Les interfaces réseau d'une microVM doivent exister au démarrage de la VM ; Firecracker ne peut pas en ajouter une plus tard. Docker, cependant, ne connecte le réseau d'un conteneur qu'après que l'exécution a créé le conteneur. La conception de référence contourne cela. Elle démarre d'abord un petit conteneur inactif qui est attaché au bon réseau et n'exécute que sleep, puis démarre l'agent à l'intérieur de l'espace de noms réseau de ce conteneur (--network container:<name>). Kata trouve les interfaces là au démarrage et les attache à la VM. Un compagnon sert exactement une VM, car Kata laisse les appareils réseau côté hôte de la VM derrière lui, donc créez et supprimez la paire ensemble et ne réutilisez pas un compagnon. Un coûte un processus inactif d'environ 12 MB.
Arrêt d'un agent bloqué
docker rm -f <agent-container> suffit. L'orchestrateur doit détecter le conteneur mort, marquer l'exécution comme échouée et supprimer le conteneur compagnon lorsqu'il démonte l'exécution.
Tout est adressé par IP
Le DNS intégré de Docker s'exécute dans l'espace de noms réseau côté hôte et est inaccessible depuis l'intérieur d'un invité. Transmettez donc les proxies aux agents en tant qu'adresses IP et attribuez une adresse IP statique aux cibles en réseau.
docker exec fonctionne, docker cp ne fonctionne pas
docker exec dans un conteneur d'agent se comporte normalement ; l'agent de Kata à l'intérieur de l'invité exécute la commande. docker cp vers ou depuis un conteneur d'agent ne fonctionne pas, car les fichiers du conteneur se trouvent sur un disque virtuel à l'intérieur de l'invité. Utilisez docker exec <container> cat <path> et similaire.
Firecracker s'exécute en tant que root à l'intérieur de sa prison
Kata démarre le jailer avec uid 0, donc le processus Firecracker est confiné par son chroot, ses espaces de noms, son filtre seccomp et son cgroup, et non par un identifiant utilisateur non privilégié. Les deux fichiers que chaque VM partage, le noyau invité et l'image, sont protégés par le drapeau immuable à la place (voir Paramètres Kata).
Kata a déprécié le runtime dont dépend Firecracker
Kata exécute Firecracker via son ancien runtime Go. Kata 4.0 a fait du nouveau runtime Rust la valeur par défaut pour ses autres hyperviseurs et a déprécié le runtime Go. En amont, on dit que le runtime Go reçoit toujours les correctifs de bogues critiques et les correctifs CVE, et qu'il pourrait être supprimé au plus tôt dans Kata 5.0. Le runtime Rust ne liste pas Firecracker parmi ses hyperviseurs, et en amont, on teste son intégration Docker principalement avec QEMU. Préparez une migration. Lorsque vous modifiez la version de Kata, répétez Validation d'un nouvel hôte. Kata peut également utiliser Cloud Hypervisor à la place de Firecracker ; l'implémentation de référence n'a pas testé ou durci cette configuration.
Journaux
Les messages du runtime de Kata, de Firecracker et de l'agent invité vont au journal : journalctl -t kata. Les problèmes de containerd et Docker se trouvent dans journalctl -u containerd et journalctl -u docker.