Backends de bac à sable
Vue d’ensemble des backends
Section intitulée « Vue d’ensemble des backends »| Backend | Valeur | Plateforme | Disponibilité |
|---|---|---|---|
| VM cloisonnée | microvm |
macOS, Linux, Windows (hyperviseur microVM) | Conditionnée à la sonde du runtime microVM ; s’applique aux terminaux interactifs — le shell s’exécute dans un rig, pas sur l’hôte |
| Natif | native |
macOS (Seatbelt), Linux et WSL2 (bubblewrap) | Sondé au démarrage ; Linux refuse une exécution qui exige des refus d’écriture fondés sur des globs de noms de fichiers, que bubblewrap ne sait pas appliquer |
| Aucun | none |
Tous | La valeur par défaut à l’analyse, celle du terminal et le repli lorsqu’aucun backend n’est disponible ou que --sandbox off est défini |
SandboxBackend.fromName renvoie none pour une valeur stockée nulle ou non reconnue. Un "docker" stocké est associé à native.
microvm est le seul backend doté d’une frontière de noyau — la charge de
travail ne s’exécute véritablement pas sur l’hôte. Il n’est jamais un repli
silencieux, dans un sens comme dans l’autre : le demander explicitement sur un
hôte incapable de démarrer une VM échoue bruyamment (« j’ai demandé une VM et
j’ai eu mon ordinateur portable » est la seule dégradation que l’enceinte ne
peut pas se permettre), et seul un défaut non spécifié retombe sur native,
avec une ligne de journal qui le dit. Le backend réel de la session est renvoyé au
client et affiché sous forme de badge, si bien qu’un terminal ne peut jamais
prétendre être cloisonné tout en s’exécutant sur l’hôte. Le cycle de vie, les
images et la sortie réseau de la VM elle-même sont traités dans la
référence des rigs.
Windows n’a pas de bac à sable natif. NativeSandboxAdapter.probe renvoie available: false sur tout hôte qui n’est ni macOS ni Linux/WSL2. Le lancement d’agents sous Windows utilise donc none. Le backend microvm est distinct : il est conditionné par la sonde du runtime microVM et s’applique aux terminaux interactifs et aux rigs, pas à l’encapsulation de bash sur l’hôte.
Résultats de la sonde
Section intitulée « Résultats de la sonde »C’est la sonde qui conditionne l’application. Elle s’exécute une fois, au démarrage du serveur.
| Hôte | available |
Remarque / indice |
|---|---|---|
| macOS | true |
sandbox-exec (Seatbelt) — isolation par espaces de noms, sans frontière de noyau |
Linux ou WSL2 avec bwrap et socat |
true |
bubblewrap — isolation par espaces de noms, sans frontière de noyau |
| Linux ou WSL2 auquel il manque l’un des deux outils | false |
requiresInstall: true, avec un indice d’installation nommant les paquets manquants |
| Toute autre plateforme | false |
Le bac à sable natif n’est pas proposé sur cette plateforme |
Le serveur consigne le résultat sur une seule ligne de démarrage : agent sandbox ON suivi de la remarque, no OS-native agent sandbox on this host suivi de l’indice, ou agent sandbox DISABLED by --sandbox off. GET /healthz ne comporte aucun champ de bac à sable.
--sandbox / CC_SERVER_SANDBOX accepte on (par défaut) ou off. C’est un désengagement, pas une activation : on signifie « encapsuler lorsque l’hôte offre un backend », jamais « en exiger un ».
Backend natif
Section intitulée « Backend natif »macOS : Seatbelt
Section intitulée « macOS : Seatbelt »Utilise le mécanisme de bac à sable Seatbelt d’Apple (le même système que celui employé par l’App Sandbox de macOS).
Le profil généré est permissif par défaut ((allow default)) et y définit des refus ciblés, car un profil entièrement à refus par défaut rend un shell interactif inutilisable — il y a trop d’appels dyld, XPC et Mach à énumérer. La conséquence pratique est qu’un agent peut encore lire la majeure partie de l’hôte ; vos copies de travail enregistrées sont protégées par des refus explicites d’écriture et de renommage, non par l’invisibilité.
- Lectures du système de fichiers : refusées pour les chemins de secrets (
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/Library/Keychainset le reste de l’ensemble de refus de lecture) - Écritures dans le système de fichiers : réinitialisées à un refus, puis des autorisations explicites de sous-chemins, les chemins à refus obligatoire (fichiers rc du shell,
.git/hooks, configuration de Claude, copies de travail protégées) étant bloqués même à l’intérieur d’une racine inscriptible.file-write-unlinkest refusé sur chaque chemin refusé et ses ancêtres, si bien qu’un renommage ne peut pas contourner un refus d’écriture - Processus : des refus
process-execpour les binaires toujours dangereux, plus un blocage de l’exécution de tout binaire depuis un répertoire inscriptible - Réseau : limité aux ports des proxys in-process plus le DNS — la boucle locale n’est pas autorisée en bloc et les sockets Unix ne sont pas autorisées. Les proxys appliquent la liste d’autorisation de domaines propre à la session (voir Sortie réseau)
- Configuration : les profils sont générés à chaque lancement à partir de la
SandboxSpec
Prérequis :
sandbox-exec(/usr/bin/sandbox-exec), présent dans toute installation macOS — aucun outil supplémentaire requis
Linux : bubblewrap
Section intitulée « Linux : bubblewrap »Utilise bubblewrap (bwrap) pour créer des espaces de noms de montage et de PID.
- Système de fichiers : crée un espace de noms de montage où seuls les chemins liés sont visibles
- Réseau : s’exécute dans un espace de noms réseau non partagé ; le trafic atteint les proxys de l’hôte via des ponts de sockets Unix
socat - Processus : isolation par espace de noms de PID
Prérequis :
bubblewrapetsocatinstallés (sudo apt-get install bubblewrap socatsous Debian/Ubuntu)- la prise en charge des espaces de noms du noyau (standard sur Linux moderne)
Bubblewrap peut masquer un chemin existant, mais ne peut pas interdire un nouveau
fichier .env, *.key ou *.pem à l’intérieur d’une liaison inscriptible. La
politique de lancement standard exige ces refus fondés sur des globs de noms de
fichiers, si bien que le lancement natif d’agents échoue actuellement en mode
fermé sous Linux/WSL2, même lorsque la sonde détecte bubblewrap. Il ne s’exécute
pas avec une politique silencieusement affaiblie. Un backend doté de règles de noms
de fichiers au moment de la création est nécessaire pour rétablir le lancement natif
sous Linux. Désactiver le bac à sable est un désengagement explicite et sans
confinement, pas un contournement équivalent.
Backend none
Section intitulée « Backend none »Aucun bac à sable. Le processus s’exécute directement sur l’hôte, avec l’accès de l’hôte au système de fichiers, au réseau et aux processus. ACP et l’outil bash du harnais bénéficient tout de même de l’assainissement de l’environnement et de la politique de commandes ; Claude Code, via NoSandboxAdapter, hérite de l’environnement de l’hôte. C’est sur cela que retombe le lancement des agents sur un hôte dépourvu de backend disponible ou avec --sandbox off, et c’est la valeur par défaut du terminal lorsqu’un client n’en nomme aucun.
Terminal hébergé par le serveur
Section intitulée « Terminal hébergé par le serveur »Le terminal est isolé selon ses propres règles, et non par la sonde de lancement. Le defaultBackend de TerminalSessionService vaut none et cc_server ne le remplace pas, si bien qu’une session de terminal exécute le shell de l’hôte à moins que le client ne demande explicitement native — le panneau de terminal de l’application de bureau ne le fait pas.
Lorsque native est demandé, le shell est encapsulé via SandboxManager sous un profil de terminal fixe : $HOME et le répertoire de travail de la session sont inscriptibles, le réseau est ouvert et la lecture de ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh et ~/Library/Keychains est refusée. Le jeton de forge en lecture seule et la passerelle de push ne s’appliquent pas — ils relèvent du lancement. Si l’encapsulation n’est pas prise en charge, la session échoue au lieu d’afficher un badge natif sur un PTY de shell hôte.
Sortie réseau
Section intitulée « Sortie réseau »Quand un bac à sable est lancé, l’accès réseau sortant est appliqué par des proxys in-process, et non par des règles de pare-feu du noyau. Sur un hôte dépourvu de backend disponible, rien de tout cela ne s’applique et un processus lancé atteint le réseau exactement comme le ferait l’utilisateur du serveur.
- Le runtime du bac à sable exécute un proxy HTTP/HTTPS et un proxy SOCKS5 sur
127.0.0.1à l’intérieur du processuscc_server, une paire par session restreinte (http_proxy.dart,socks_proxy.dart). Les exécutions concurrentes ne partagent pas de paire. - Les processus isolés reçoivent des variables d’environnement de proxy (
HTTP_PROXY/HTTPS_PROXY→ le proxy HTTP,ALL_PROXY→ le proxy SOCKS ;GIT_SSH_COMMANDachemine git-over-SSH via le proxy SOCKS). Sous Linux, l’espace de noms réseau n’est pas partagé, si bien que les proxys sont la seule sortie ; sous macOS, le bac à sable partage la boucle locale de l’hôte et leur parle directement. - L’hôte cible de chaque connexion est comparé à la liste d’autorisation de domaines de la session ; tout le reste est refusé. Deux formes de joker, chacune avec exactement un
*: un*.example.comen tête correspond à n’importe quel sous-domaine (y comprisa.b.example.com) mais pas au domaine apex lui-même ; unbedrock.*.amazonaws.comen milieu de libellé correspond à exactement un libellé (bedrock.us-east-1.amazonaws.com, et nonbedrock.evil.attacker.amazonaws.com). - La liste d’autorisation est résolue par session à partir de la base curatée (
kBaselineAllowedDomains: fournisseurs de LLM, hébergement Git, registres de paquets), plus les domaines GitHub (kGithubDomains), plusSandboxSpec.egressAllowlist. Le chemin de lancement ne transmet jamais d’entréesegressAllowlistsupplémentaires, si bien qu’en pratique chaque exécution obtient la base plus GitHub. - Une liste de refus fixe (
kBaselineDeniedDomains: points de terminaison de métadonnées cloud, récepteurs de télémétrie) l’emporte sur toutes les autorisations. networkEnabled: falsedémarre quand même les proxys de la session, mais la liste d’autorisation est vide, si bien que toute connexion sortante est refusée. Le lancement le règle au démarrage de l’exécution à partir de la règle Accéder au réseau : un refus désactive le réseau, autoriser et demander d’abord le laissent activé.
SandboxSpec
Section intitulée « SandboxSpec »La spécification transmise à SandboxPort.launch :
| Champ | Type | Description |
|---|---|---|
sessionId |
String |
Identifiant de session stable (généralement l’identifiant de l’espace) |
workspaceId |
String |
Identifiant de l’espace de travail propriétaire |
agentId |
String? |
Agent actuellement lié au bac à sable, le cas échéant |
bindMounts |
List<SandboxBindMount> |
Montages hôte→invité ; le bac à sable ne voit que les chemins d’hôte listés ici |
networkEnabled |
bool (par défaut true) |
Réglé au lancement à partir de la règle de sortie réseau (désactivé seulement si elle aboutit à un refus). Lorsqu’il est désactivé, les proxys de la session démarrent quand même, mais la liste d’autorisation est vide, si bien que toute connexion sortante est refusée |
egressAllowlist |
List<String> (par défaut []) |
Domaines de sortie supplémentaires autorisés ; jokers pris en charge (*.example.com, ainsi qu’une forme en milieu de libellé unique). Le lancement ne renseigne jamais ce champ, si bien qu’une exécution encapsulée obtient la base curatée plus les domaines GitHub |
guestWorkdir |
String? |
Répertoire de travail par défaut à l’intérieur du bac à sable ; les appels exec individuels peuvent le remplacer |
mode |
Mode (par défaut chat) |
Définit les règles d’écriture du système de fichiers : chat garde les montages par liaison inscriptibles ; review, plan et orchestrate sont en lecture seule |
protectedPaths |
List<String> (par défaut []) |
Chemins d’hôte qui ne doivent jamais être inscriptibles à l’intérieur du bac à sable, quel que soit le mode |
runnerStateDirs |
List<String> (par défaut []) |
Répertoires de l’hôte où l’exécuteur conserve son propre état, inscriptibles dans tous les modes (un CLAUDE_CONFIG_DIR géré par Control Center est le cas actuel) |
execGrantRoots |
List<String> (par défaut []) |
Arborescences de répertoires approuvées par l’opérateur qui rouvrent le blocage d’exécution dans les répertoires inscriptibles sous macOS. Linux les ignore — bwrap n’a aucun blocage d’exécution $HOME à rouvrir |
protectedPaths contient les copies de travail enregistrées d’origine des dépôts, résolues à chaque lancement à partir des dépôts de l’espace de travail. Les agents travaillent exclusivement dans des arbres de travail en copie sur écriture propres à chaque conversation, si bien que les originaux ne doivent jamais être inscriptibles depuis l’intérieur du bac à sable — sous macOS, l’autorisation d’écriture globale sur $HOME accordée par Seatbelt les laisserait sinon inscriptibles via bash. Ils rejoignent l’ensemble de refus d’écriture des secrets dans tous les modes, chat compris.
Chaque chemin de refus de lecture et d’écriture est émis à la fois dans son orthographe littérale et dans sa forme résolue par lien symbolique. Le noyau compare une règle de refus au chemin résolu, si bien qu’une règle écrite pour un chemin symbolique ne se déclenche jamais — et sous macOS, c’est le cas courant plutôt que l’exception, puisque /tmp se résout en /private/tmp et /var/folders/… en /private/var/folders/…. Les entrées contenant * ou ? sont traitées comme des globs et laissées telles quelles ; un chemin qui ne se résout pas est conservé tel quel.
SandboxBindMount
Section intitulée « SandboxBindMount »| Champ | Type | Description |
|---|---|---|
hostPath |
String |
Chemin absolu sur l’hôte |
guestPath |
String |
Chemin à l’intérieur du bac à sable (avec le bac à sable natif, il est égal à hostPath ; conservé pour la symétrie des adaptateurs) |
readOnly |
bool (par défaut false) |
Monte en lecture seule lorsque vrai |
SandboxHandle
Section intitulée « SandboxHandle »Renvoyé par SandboxPort.launch :
| Champ | Type | Description |
|---|---|---|
sessionId |
String |
Identifiant de session |
backend |
SandboxBackend |
Le backend en cours d’exécution |
state |
SandboxState |
État du cycle de vie |
error |
Object? |
Défini lorsque state vaut error |
details |
Map<String, Object?> |
Comptabilité interne à l’adaptateur (répertoire de travail, PID, chemin du profil, etc.) |
SandboxState
Section intitulée « SandboxState »| État | Description |
|---|---|
created |
Spécification créée, mais la VM n’a pas encore démarré |
warm |
En cours d’exécution et prêt à exécuter des commandes |
active |
Exécute actuellement une commande |
suspended |
En pause / avec point de contrôle sur disque pour économiser la RAM |
destroyed |
Démonté ; le descripteur n’est plus valide |
error |
Le lancement a échoué — voir SandboxHandle.error |
Événements du bac à sable
Section intitulée « Événements du bac à sable »| Type d’événement | Description |
|---|---|
stdout |
Sortie standard du bac à sable |
stderr |
Erreur standard du bac à sable |
exit |
Le processus du bac à sable s’est terminé (porte exitCode) |
starting |
Le bac à sable démarre |
ready |
Le bac à sable est prêt à accepter des appels exec |
killed |
Processus tué par l’hôte (OOM, expiration, arrêt manuel) |
violation |
Une politique du bac à sable a été violée (porte une SandboxViolation) |
SandboxViolation
Section intitulée « SandboxViolation »| Champ | Type | Description |
|---|---|---|
action |
String |
Le verbe refusé (par ex. file-read*, network-outbound) |
target |
String |
Chemin ou hôte qui était la cible de l’opération refusée |
raw |
String? |
Ligne de journal brute, utile pour le débogage |
Voir aussi
Section intitulée « Voir aussi »- Bac à sable et sécurité
- Politiques de bac à sable
- Garde-fous
- CLI cc_server : l’indicateur
--sandbox