Retour à tous les articles
Ingénierie15 avril 202616 minute de lecture

Sandbox d'agent IA : pourquoi l'exécution de code isolée n'est pas négociable

L'immersion technique d'un ingénieur senior dans les sandboxes d'agents IA, les microVM E2B, le provisionnement en moins d'une seconde, et le modèle de menace que vous ne pouvez pas ignorer. Leçons d'un an en production.

Par Nico Jaroszewski
CodeCourier Founder

Si vous laissez un agent IA exécuter du code sur une infrastructure partagée, vous avez déjà perdu. C'est la conclusion inconfortable à laquelle nous sommes arrivés après un an d'exploitation de charges de travail IA en production chez CodeCourier. Le modèle n'est pas malveillant ; les entrées le sont. L'injection de prompt, l'empoisonnement de la chaîne d'approvisionnement, les processus incontrôlés, et les caches silencieusement corrompus trouveront chaque faille dans un environnement non isolé. La seule réponse crédible est une sandbox d'agent IA : une machine Linux fraîche et isolée au niveau matériel qui démarre en moins d'une seconde, accepte les instructions de l'agent, et est détruite à l'instant où l'exécution se termine.

Cet article est le pilier technique que nous promettions. Il couvre le modèle de menace, la comparaison entre conteneurs, microVM, et VM complètes, comment nous provisionnons des microVM Firecracker soutenues par E2B en moins d'une seconde, comment nous gardons les systèmes de fichiers et les réseaux étanches, comment les secrets ne persistent jamais, comment nous enregistrons chaque action pour l'audit, et les sept leçons concrètes que nous avons apprises à la dure. Si vous construisez des agents qui touchent au code, c'est la question de substrat qui décide si vous pouvez dormir tranquille le vendredi soir.

Pourquoi les sandboxes ne sont pas négociables pour les ingénieurs IA

Une sandbox d'agent IA est un environnement d'exécution éphémère et isolé - typiquement une VM ou une microVM éphémère - qu'un agent autonome utilise pour exécuter du code, des commandes, et des outils sans accès aux ressources de l'hôte, aux autres locataires, ou à un état persistant. C'est la différence entre un agent qui rédige une pull request et un agent qui introduit une CVE dans votre chaîne d'approvisionnement.

Trois propriétés font d'une sandbox une sandbox, pas juste un conteneur avec de bonnes intentions :

  1. Isolation matérielle. La frontière est appliquée par l'hyperviseur, pas par les namespaces du noyau à côté desquels il s'exécute. Une évasion de conteneur devient une évasion de microVM - des ordres de grandeur plus difficile.
  2. Éphémérité. L'état du disque, de la RAM, et du réseau disparaît à la fin de l'exécution. Pas de caches, pas de sockets abandonnées, pas de fichiers temporaires avec des jetons porteurs.
  3. Provisionnement en moins d'une seconde. Si le démarrage à froid est lent, les ingénieurs le contournent, en partageant des sandboxes entre exécutions. À l'instant où cela se produit, l'isolation disparaît.

Sautez l'une des trois et vous n'avez pas une sandbox. Vous avez un conteneur avec un budget marketing.

Le modèle de menace - ce qui va mal sans isolation

Chaque équipe à qui je parle sous-estime la surface d'attaque d'un agent autonome. Le modèle est non déterministe, les entrées sont contrôlées par l'attaquant, et les outils sont puissants par conception. Voici le catalogue de menaces contre lequel nous avons construit notre architecture.

1. Échec de confinement de l'injection de prompt

Un ticket d'issue, un README, un commentaire dans une dépendance - tout texte que l'agent ingère est une instruction qu'il pourrait suivre. Nous avons vu des agents convaincus de faire un git push vers un dépôt distant contrôlé par un attaquant, d'exfiltrer des fichiers .env via un one-liner curl, ou d'installer un paquet dont le script post-installation écrit dans ~/.ssh/authorized_keys. Une sandbox n'arrête pas l'injection de prompt. Elle contient le rayon d'impact à un disque qui sera détruit dans quinze minutes.

2. Empoisonnement de la chaîne d'approvisionnement

Chaque npm install exécute du code arbitraire. Chaque pip install aussi. Un paquet au nom similaire (typosquatting), un mainteneur compromis, un hook post-installation malveillant - votre agent les exécutera tous joyeusement. Sans sandbox, l'hôte reçoit la porte dérobée. Avec une sandbox, c'est la VM jetable qui la reçoit, et personne ne s'en soucie.

3. Exfiltration via DNS, HTTP, ou git

Un canal d'exfiltration déterminé n'est qu'à un curl -d @secrets.txt de distance. Sur un hôte partagé, ce trafic se fond dans le trafic légitime. Dans une sandbox avec une liste d'autorisation de sortie refusant par défaut, la requête échoue et nous la journalisons.

4. Processus incontrôlés et épuisement des ressources

Un agent qui relance un test instable dans une boucle while true dévorera chaque cycle CPU qu'il peut atteindre. Sans quotas par VM, une seule mauvaise exécution fait tomber l'hôte et tout le monde dessus. Avec eux, la VM atteint son plafond, l'agent reçoit le signal OOM, et le reste de la plateforme ne remarque rien.

5. Fuite de données inter-locataires

Si deux clients partagent un processus, un noyau, ou même un système de fichiers, vous avez construit un canal auxiliaire. Les attaques d'exécution spéculative, la traversée de /proc, les répertoires temporaires partagés - l'histoire de la sécurité multi-locataire est l'histoire de la découverte de nouvelles variantes de ce bug. Une microVM avec son propre noyau élimine la catégorie.

Conteneur contre microVM contre VM complète - la comparaison qui compte

On me demande sans cesse pourquoi nous n'avons pas simplement utilisé Docker. Voici le tableau que je renvoie.

PropriétéConteneur (Docker)microVM (Firecracker / E2B)VM complète (KVM, EC2)
Frontière d'isolationNamespaces du noyau, cgroupsHyperviseur, noyau dédiéHyperviseur, noyau dédié
Démarrage à froid100 ms - 2 s150 ms - 400 ms20 s - 90 s
Surcharge mémoire~5 Mo~5 Mo100 - 500 Mo
Densité par hôteCentainesMilliersDizaines
Résistance aux exploits du noyauFaible - noyau partagéÉlevée - noyau séparé par VMÉlevée - noyau séparé par VM
Isolation du système de fichiersEn couches, couches souvent partagéesPériphérique bloc par VMPériphérique bloc par VM
Adéquation pour code non fiableRisquéConçu pour celaOui, mais lent

Les conteneurs gagnent sur l'outillage et l'écosystème. Les VM complètes ne gagnent rien pour notre cas d'usage - elles sont trop lentes à provisionner par requête. Les microVM Firecracker frappent le seul point de la courbe qui compte pour les agents IA : une isolation de niveau matériel à une vitesse de démarrage de niveau conteneur. C'est la raison technique pour laquelle E2B existe et la raison pour laquelle nous avons misé dessus.

Comment CodeCourier provisionne des sandboxes en moins d'une seconde

L'architecture est construite autour de quatre primitives : un pool préchauffé, la restauration d'instantanés, des images modèles, et une couche d'orchestration mince entre notre plan de contrôle et l'API E2B. Voici le chemin qu'une sandbox emprunte de la requête à la disponibilité.

  1. La requête atterrit au gestionnaire de sandboxes. L'exécuteur de workflow demande une sandbox avec un modèle (par ex. node20-postgres), une région, une forme CPU/RAM, et une politique de sortie.
  2. Recherche dans le pool. Nous maintenons un pool chaud de microVM en pause par modèle par région. Si une correspondance existe, nous sautons complètement le démarrage.
  3. Restauration d'instantané. Une VM correspondante est reprise depuis un instantané mémoire en environ 120 à 180 ms. Le noyau, le gestionnaire de paquets, et l'exécution du langage sont déjà en RAM.
  4. Chemin froid. Si le pool est vide, nous démarrons une microVM fraîche depuis l'image modèle de base. Firecracker signale prêt en 150 à 250 ms ; le temps total incluant notre surcharge d'orchestration s'établit à 300 à 600 ms.
  5. Injection des secrets et de la politique. Des identifiants par étape de courte durée sont remis à l'agent via un canal d'initialisation en mémoire uniquement. Les règles de sortie sont appliquées dans le namespace réseau de l'hôte avant que l'agent n'exécute sa première commande.
  6. Remise du handle au workflow. L'orchestrateur retourne un ID de sandbox opaque. L'agent commence à travailler.

Médiane de bout en bout, mesurée sur les 30 derniers jours de production : 520 ms. p99 : 1,4 s. Chemin froid (pas de hit de pool) : 1,8 s p50. C'est le chiffre qui permet au tableau de bord orienté utilisateur de dire « démarrage de la sandbox » sans afficher de spinner.

Un extrait représentatif de notre orchestrateur (TypeScript, simplifié) :

import { Sandbox } from 'e2b';

async function provision(opts: {
  template: string;
  region: 'us-east' | 'eu-west';
  egressAllowlist: string[];
  stepSecrets: Record<string, string>;
}) {
  const warm = await pool.tryClaim(opts.template, opts.region);
  const sbx = warm ?? await Sandbox.create(opts.template, {
    region: opts.region,
    timeoutMs: 15 * 60 * 1000,
  });

  await applyEgressPolicy(sbx.id, opts.egressAllowlist);
  await injectSecrets(sbx.id, opts.stepSecrets); // memory-only

  return sbx;
}

La machinerie complète - dimensionnement du pool, éviction, générations d'instantanés, basculement de région - vit derrière cette surface. Voyez comment nous exploitons les sandboxes pour la vue côté produit.

Isolation du système de fichiers et du réseau en pratique

L'isolation est une propriété que vous devez appliquer à chaque couche, sinon vous n'en avez aucune. Nous traitons le système de fichiers et le réseau comme les deux portes blindées principales.

Système de fichiers. Chaque sandbox obtient son propre périphérique bloc soutenu par une copie de l'image modèle. Il n'y a pas de superposition partagée avec l'hôte. L'agent a les droits root à l'intérieur de la VM et exactement rien à l'extérieur. Les écritures ne persistent pas d'une exécution à l'autre sauf si le workflow pousse explicitement des artefacts vers le stockage d'objets ou vers git. Quand l'exécution se termine, le périphérique bloc est effacé avant que le slot ne retourne au pool.

Réseau. La politique par défaut est un refus total de la sortie avec une liste d'autorisation organisée : l'hébergeur git du client, les registres de paquets courants (npmjs.org, pypi.org, crates.io), et le point de terminaison LLM. Tout le reste est rejeté au pare-feu de l'hôte. Les clients peuvent étendre la liste d'autorisation par projet, mais jamais par exécution, et jamais via l'agent lui-même - cela permettrait à l'injection de prompt de réécrire ses propres murs.

Le DNS est résolu via notre propre résolveur qui journalise chaque recherche. Un nombre surprenant de tentatives d'exfiltration apparaissent comme des requêtes DNS vers des domaines appartenant à l'attaquant bien avant qu'une requête HTTP ne se déclenche. Nous les attrapons là.

Gestion des secrets - ne jamais fuiter, ne jamais persister

Chaque bug de secrets que nous avons jamais livré provenait d'un secret qui a vécu plus longtemps que nécessaire. Notre règle est : de courte durée, à portée étroite, jamais sur disque, jamais dans les journaux. Concrètement :

  • Des jetons par étape, pas par exécution. Un workflow avec douze étapes frappe douze identifiants distincts, chacun valide pour la durée de cette étape plus une petite fenêtre de grâce.
  • Injection en mémoire uniquement. Les secrets passent par un fichier d'environnement soutenu par tmpfs qui se démonte à la sortie du processus. Ils ne touchent jamais le stockage persistant.
  • Nettoyage des journaux au niveau de la couche de streaming. Stdout et stderr passent par un rédacteur avant d'atteindre notre base de données, le tableau de bord, ou tout œil humain.
  • Aucun magasin de secrets lisible par l'agent. L'agent ne peut pas énumérer les secrets disponibles. Il ne peut utiliser que ceux que le workflow a explicitement liés à l'étape actuelle.
  • Révocation automatique en cas d'anomalie. Si notre pipeline d'audit voit un identifiant utilisé en dehors de sa portée déclarée, il est révoqué en quelques secondes.

La conformité documente cela en détail - voyez nos pages SOC 2 et RGPD - mais la substance technique est les cinq points ci-dessus.

Observabilité - enregistrer chaque action de l'agent pour l'audit

Un agent autonome sans magnétophone est un passif. Nous diffusons chaque événement significatif hors de la sandbox en temps réel et le persistons dans un stockage immuable :

  • Chaque commande exécutée, avec les arguments, le répertoire de travail, le code de sortie, et la durée.
  • Chaque fichier écrit ou lu au-dessus d'un seuil de taille configurable, avec un hachage de contenu.
  • Chaque connexion réseau sortante, l'IP résolue, le port de destination, et le nombre d'octets transférés.
  • Chaque appel LLM effectué depuis l'intérieur de la sandbox, y compris le modèle, les comptages de tokens, et les appels d'outils émis par le modèle.
  • Chaque événement de matérialisation de secret, nettoyé de la valeur du secret elle-même.

Le résultat est une chronologie médico-légale que vous pouvez rejouer dans notre tableau de bord ou canaliser vers votre SIEM. Quand une équipe de sécurité d'entreprise demande « qu'a réellement fait l'agent à 14h32 le 4 mars ? », nous répondons en quelques secondes, pas en jours. Le même pipeline alimente notre red-team nocturne - voyez la vue d'ensemble de la sécurité pour la configuration adverse.

Leçons d'un an d'exploitation de l'IA dans des sandboxes

Lire sur l'isolation est une chose. L'exploiter sur de vraies charges de travail en est une autre. Voici les sept leçons pour lesquelles nous avons réellement payé, avec les chiffres associés.

Leçon 1 - les caches partagés sont un incident de sécurité qui n'attend que de se produire

Notre premier prototype partageait un cache npm entre les sandboxes pour économiser 8 à 12 secondes sur les installations. Cela fonctionnait à merveille jusqu'à ce qu'un agent installe un paquet au nom similaire dont le script post-installation écrivait une porte dérobée dans le répertoire de cache. Les vingt exécutions suivantes l'ont récupérée. Nous avons supprimé le cache partagé le jour même. La correction a été de cuire les 200 paquets les plus utilisés dans l'image modèle - cela a récupéré la majeure partie du gain de vitesse sans le risque d'état partagé.

Leçon 2 - les pools préchauffés battent les démarrages à froid optimisés

Nous avons passé deux semaines à gratter 80 ms du chemin froid de Firecracker. Puis nous avons construit un pool chaud et récupéré 280 ms gratuitement à chaque hit de cache. Leçon : n'optimisez pas le chemin lent avant de l'avoir éliminé. Aujourd'hui, 87% de nos provisionnements de sandboxes touchent le pool. Le temps de provisionnement médian est passé de 1,4 s à 520 ms en une semaine.

Leçon 3 - les jetons de longue durée sont un but contre son camp

Nous avions l'habitude de frapper un seul jeton git-push par exécution de workflow, valide pour toute l'exécution. C'était pratique. C'était aussi à une seule injection de prompt du désastre. Nous avons reconstruit la couche des identifiants pour frapper des jetons par étape avec un TTL de 60 secondes plus une poignée de main de renouvellement explicite. Notre fenêtre d'exposition d'identifiants dans le pire des cas est passée de 40 minutes à moins de 2.

Leçon 4 - l'observabilité se rentabilise en semaine trois

La première fois qu'un client a demandé pourquoi son workflow avait pris 14 minutes de plus que d'habitude, nous avons rejoué la chronologie, trouvé un npm install instable qui relançait contre un miroir lent, et corrigé le modèle le même après-midi. Cet incident unique a justifié toute la pile d'observabilité. Trois mois plus tard, nous utilisons ces chronologies davantage comme outil de débogage que de sécurité.

Leçon 5 - l'ordonnancement à part équitable arrête les voisins bruyants

Un client a fait tourner un workflow qui générait 100 suites de tests parallèles dans une seule sandbox. La sandbox allait bien - mais le budget I/O de l'hôte non. Après avoir ajouté des quotas I/O par sandbox et des plafonds de concurrence par locataire avec un ordonnanceur à part équitable, la latence p99 pour tous les autres a chuté de 38% et nous n'avons plus jamais vu le problème.

Leçon 6 - les instantanés sont une fonctionnalité de phase un, pas de phase deux

Nous avons traité les instantanés de sandbox comme un plus agréable pendant les six premiers mois. Les clients exécutant des workflows de plusieurs heures rencontraient des limites de débit, des pannes de modèle transitoires, ou des tests instables et devaient repartir de zéro à chaque fois. Quand nous avons livré la prise d'instantanés, le coût moyen d'une exécution réussie a chuté de 23% et les tickets « le workflow est mort sans raison » signalés par les clients sont tombés à zéro en deux semaines.

Leçon 7 - le journal d'audit est le produit

Chaque cycle de vente entreprise atteint éventuellement la question « prouvez que l'agent a fait exactement ce qu'il prétend avoir fait ». Nous pensions que la réponse était le résultat. La réponse est la chronologie. Traitez votre journal d'audit comme une interface utilisateur de premier ordre, pas comme un artefact de conformité. Notre vélocité de deals a à peu près doublé après que nous avons livré la vue chronologique dans notre tableau de bord.

Quand NE PAS utiliser de sandboxes

Je ne suis pas dogmatique là-dessus. Il existe de vrais cas où une sandbox est excessive ou même contre-productive :

  • Inférence pure, pas d'utilisation d'outils. Si l'agent ne fait que lire depuis une API et écrire un résumé Markdown, vous n'avez pas besoin d'une microVM. Vous avez besoin d'une fonction sans état.
  • UX interactive hautement sensible à la latence où vous contrôlez chaque entrée. Un modèle de complétion de code s'exécutant sur la propre machine d'un développeur, sans entrée non fiable dans la boucle, est sa propre frontière de confiance.
  • Plugins IDE profondément intégrés. Si l'agent agit par définition en tant que le développeur, le sandboxer par rapport au dépôt du développeur va à l'encontre du but. Sandboxez le réseau, pas le système de fichiers.

La ligne que nous traçons chez CodeCourier : tout agent qui exécute du code au nom d'un utilisateur autre que lui-même s'exécute dans une sandbox. Tout le reste est au cas par cas. Si vous utilisez Issue Sessions, Personas, ou le Workflow Builder, vous êtes du côté sandbox de la ligne.

FAQ - sandboxes d'agents IA

Qu'est-ce qu'une sandbox d'agent IA ?

Une sandbox d'agent IA est un environnement d'exécution éphémère et isolé au niveau matériel - généralement une microVM - qu'un agent autonome utilise pour exécuter du code, installer des paquets, exécuter des commandes, et utiliser des outils. Elle est détruite à la fin de l'exécution, si bien que rien de ce que fait l'agent ne persiste sauf si le workflow l'exporte explicitement.

Pourquoi une microVM est-elle meilleure qu'un conteneur Docker pour les agents IA ?

Un conteneur Docker partage le noyau de l'hôte. Un exploit du noyau, une capacité mal configurée, ou une évasion de namespace donne l'hôte à un attaquant. Une microVM exécute son propre noyau sous un hyperviseur ; une évasion nécessite de briser l'hyperviseur, une cible bien plus difficile. Pour du code non fiable - et tout code généré par un LLM est, par définition, non fiable - les microVM sont le choix prudent.

Comment E2B atteint-il un démarrage de sandbox en moins d'une seconde ?

E2B utilise des microVM Firecracker, qui démarrent en 100 à 250 ms parce qu'elles suppriment chaque périphérique, routine BIOS, et module de noyau dont une charge de travail serverless n'a pas besoin. Par-dessus cela, nous maintenons un pool préchauffé de VM en pause par modèle. Un hit de pool se restaure depuis un instantané mémoire en environ 120 à 180 ms.

L'injection de prompt peut-elle s'échapper d'une sandbox ?

L'injection de prompt ne peut pas franchir la frontière de la sandbox elle-même - cela est appliqué par l'hyperviseur, pas par le modèle. Ce que l'injection de prompt peut faire, c'est convaincre l'agent de détourner les ressources qu'il possède légitimement à l'intérieur de la sandbox : exfiltrer via un point de terminaison autorisé, pousser vers le mauvais dépôt git distant, ou brûler du crédit. La défense est en couches : des listes d'autorisation de sortie strictes, des identifiants par étape avec des portées étroites, et une observabilité qui signale les appels d'outils anormaux en temps réel.

Combien de temps vit une sandbox ?

Par défaut, quinze minutes de temps d'inactivité avant destruction automatique, avec un maximum absolu configurable par workflow. Les workflows longs utilisent notre protocole d'instantané pour mettre en pause et reprendre sur la durée de vie d'une seule exécution.

Où vont les artefacts client après la destruction de la sandbox ?

Partout où le workflow les place explicitement. Les branches sont poussées vers votre hébergeur git. Les artefacts sont téléversés vers votre stockage d'objets. Rien d'autre ne survit. Le périphérique bloc est effacé avant que le slot ne retourne au pool.

La sandbox d'agent IA est-elle conforme à SOC 2 et au RGPD ?

Oui. CodeCourier est certifié SOC 2 Type II et exploite un plan de données exclusivement UE pour les charges de travail sensibles au RGPD. Voyez SOC 2 et RGPD pour les contrôles complets.

Où puis-je en apprendre plus ?

Commencez par nos guides, parcourez le blog d'ingénierie, ou lisez à propos de l'équipe. Si vous voulez nous parler d'une charge de travail spécifique, contactez-nous.

Nico Jaroszewski
CodeCourier Founder
Balises
#sandbox agent ia#sandbox e2b#execution code isolee#execution code ia securisee#firecracker#microvm#prompt injection#securite ia#isolation agent#infrastructure#devops#securite
Partager

Continuez à lire

Gratuit pendant 14 jours · pas de carte de crédit

Embauchez votre premier ingénieur IA.
Expédier avant l'heure du déjeuner.

5 minutes pour embarquer. Premier PR dans l'heure. Annulez à tout moment.