Backends del entorno aislado
Resumen de los backends
Sección titulada «Resumen de los backends»| Backend | Valor | Plataforma | Disponibilidad |
|---|---|---|---|
| VM aislada | microvm |
macOS, Linux, Windows (hipervisor de microVM) | Condicionado por el sondeo del runtime de microVM; se aplica a los terminales interactivos: el shell se ejecuta dentro de un rig, no en el host |
| Nativo | native |
macOS (Seatbelt), Linux y WSL2 (bubblewrap) | Se sondea al arrancar; Linux rechaza una ejecución que exija denegaciones de escritura por glob de nombre de archivo, que bubblewrap no puede aplicar |
| Sin aislamiento | none |
Todas | El valor predeterminado al analizar, el predeterminado del terminal y el recurso de reserva cuando no hay ningún backend disponible o se ha establecido --sandbox off |
SandboxBackend.fromName devuelve none cuando el valor almacenado es nulo o no se reconoce. Un "docker" almacenado se asigna a native.
microvm es el único backend con una frontera de kernel: la carga de trabajo no se ejecuta realmente en el host. Nunca es un recurso de reserva silencioso en ninguna de las dos direcciones: solicitarlo de forma explícita en un host que no puede arrancar una VM falla de forma ruidosa («pedí una VM y obtuve mi portátil» es la única degradación que el recinto no puede permitirse), y solo un predeterminado sin especificar baja a native, dejando una línea de registro que lo indica. El backend real de la sesión se comunica de vuelta al cliente y se marca con una insignia, así que un terminal nunca puede afirmar que está en un recinto mientras se ejecuta en el host. El ciclo de vida, las imágenes y la salida de red de la propia VM se tratan en la referencia de rigs.
Windows no tiene entorno aislado nativo. NativeSandboxAdapter.probe devuelve available: false en cualquier host que no sea macOS o Linux/WSL2. Por tanto, el despacho de agentes en Windows usa none. El backend microvm es aparte: está condicionado por el sondeo del runtime de microVM y se aplica a los terminales interactivos y a los rigs, no a envolver bash en el host.
Resultados del sondeo
Sección titulada «Resultados del sondeo»El sondeo es lo que condiciona la aplicación. Se ejecuta una vez, al arrancar el servidor.
| Host | available |
Nota o indicación |
|---|---|---|
| macOS | true |
sandbox-exec (Seatbelt): aislamiento de espacios de nombres, sin frontera de kernel |
Linux o WSL2 con bwrap y socat |
true |
bubblewrap: aislamiento de espacios de nombres, sin frontera de kernel |
| Linux o WSL2 sin alguna de las herramientas | false |
requiresInstall: true, con una indicación de instalación que nombra los paquetes que faltan |
| Cualquier otra plataforma | false |
El entorno aislado nativo no se ofrece en esta plataforma |
El servidor registra el resultado en una sola línea de arranque: agent sandbox ON más la nota, no OS-native agent sandbox on this host más la indicación, o agent sandbox DISABLED by --sandbox off. GET /healthz no incluye ningún campo del entorno aislado.
--sandbox / CC_SERVER_SANDBOX acepta on (predeterminado) u off. Es una renuncia, no una activación: on significa «envuelve cuando el host ofrezca un backend», nunca «exige uno».
Backend nativo
Sección titulada «Backend nativo»macOS: Seatbelt
Sección titulada «macOS: Seatbelt»Usa el mecanismo de entorno aislado Seatbelt de Apple (el mismo sistema que emplea macOS App Sandbox).
El perfil generado es permisivo de forma predeterminada ((allow default)) y recorta denegaciones, porque un perfil con denegación total por defecto hace que un shell interactivo sea inutilizable: hay demasiadas llamadas dyld, XPC y Mach que enumerar. La consecuencia práctica es que un agente todavía puede leer buena parte del host; tus copias de trabajo registradas están protegidas por denegaciones explícitas de escritura y de renombrado, no por invisibilidad.
- Lecturas del sistema de archivos: denegadas para las rutas secretas (
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/Library/Keychainsy el resto del conjunto de lectura denegada) - Escrituras del sistema de archivos: se reajustan a denegar y después se permiten subrutas explícitas, con las rutas de denegación obligatoria (archivos rc del shell,
.git/hooks, la configuración de Claude, las copias de trabajo protegidas) bloqueadas incluso dentro de una raíz escribible.file-write-unlinkse deniega en cada ruta denegada y en sus ancestros, de modo que un rename no puede eludir una denegación de escritura - Procesos: denegaciones de
process-execpara los binarios siempre peligrosos, más un bloqueo a ejecutar cualquier cosa desde un directorio escribible - Red: restringida a los puertos del proxy en proceso más DNS: loopback no se permite sin más y los sockets Unix no se permiten. Los proxies aplican la lista de permitidos de dominios por sesión (consulta Salida de red)
- Configuración: los perfiles se generan en cada lanzamiento a partir del
SandboxSpec
Requisitos:
sandbox-exec(/usr/bin/sandbox-exec), presente en toda instalación de macOS: no hace falta ninguna herramienta adicional
Linux: bubblewrap
Sección titulada «Linux: bubblewrap»Usa bubblewrap (bwrap) para crear espacios de nombres de montaje y de PID.
- Sistema de archivos: crea un espacio de nombres de montaje en el que solo son visibles las rutas montadas con bind
- Red: se ejecuta en un espacio de nombres de red no compartido; el tráfico llega a los proxies del host a través de puentes de sockets Unix de
socat - Procesos: aislamiento del espacio de nombres de PID
Requisitos:
bubblewrapysocatinstalados (sudo apt-get install bubblewrap socaten Debian/Ubuntu)- Compatibilidad con espacios de nombres del kernel (estándar en Linux moderno)
Bubblewrap puede ocultar una ruta existente, pero no puede prohibir un archivo .env, *.key o *.pem nuevo dentro de un bind escribible. La política de despacho estándar exige estas denegaciones por glob de nombre de archivo, así que hoy el despacho nativo de agentes falla en cerrado en Linux/WSL2 incluso cuando el sondeo encuentra bubblewrap. No se ejecuta con una política silenciosamente más débil. Para restaurar el despacho nativo en Linux se necesita un backend con reglas de nombre de archivo en el momento de la creación. Desactivar el entorno aislado es una renuncia explícita y sin confinamiento, no un equivalente.
Backend sin aislamiento
Sección titulada «Backend sin aislamiento»Ningún entorno aislado. El proceso se ejecuta directamente en el host, con el acceso al sistema de archivos, a la red y a los procesos que tiene el host. ACP y la herramienta bash del arnés siguen recibiendo el entorno saneado y la política de comandos; Claude Code a través de NoSandboxAdapter hereda el entorno del host. Es aquello a lo que recurre el despacho de agentes en un host sin ningún backend disponible o con --sandbox off, y es el valor predeterminado del terminal cuando un cliente no indica ninguno.
Terminal alojado en el servidor
Sección titulada «Terminal alojado en el servidor»El terminal se aísla según sus propias reglas, no por el sondeo del despacho. El defaultBackend de TerminalSessionService es none y cc_server no lo sobrescribe, así que una sesión de terminal ejecuta el shell del host salvo que el cliente pida native explícitamente: el panel de terminal de la aplicación de escritorio no lo hace.
Cuando se solicita native, el shell se envuelve a través de SandboxManager bajo un perfil de terminal fijo: $HOME y el directorio de trabajo de la sesión son escribibles, la red está abierta y se deniega la lectura de ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh y ~/Library/Keychains. El token de forja de solo lectura y la pasarela de push no se aplican: son cosa del despacho. Si el envoltorio no es compatible, la sesión falla en lugar de mostrar una insignia nativa sobre un PTY del shell del host.
Salida de red
Sección titulada «Salida de red»Cuando se lanza un entorno aislado, el acceso saliente a la red lo aplican proxies en proceso, no reglas de cortafuegos del kernel. En un host sin ningún backend disponible nada de esto se aplica, y un proceso lanzado llega a la red exactamente igual que lo haría el usuario del servidor.
- El runtime del entorno aislado ejecuta un proxy HTTP/HTTPS y un proxy SOCKS5 en
127.0.0.1dentro del procesocc_server, un par por sesión restringida (http_proxy.dart,socks_proxy.dart). Las ejecuciones simultáneas no comparten un par. - Los procesos aislados reciben variables de entorno de proxy (
HTTP_PROXY/HTTPS_PROXY→ el proxy HTTP,ALL_PROXY→ el proxy SOCKS;GIT_SSH_COMMANDencamina git por SSH a través del proxy SOCKS). En Linux el espacio de nombres de red no se comparte, así que los proxies son la única salida; en macOS el entorno aislado comparte el loopback del host y habla directamente con ellos. - El host de destino de cada conexión se compara con la lista de permitidos de dominios de la sesión; todo lo demás se deniega. Hay dos formas de comodín, cada una con exactamente un
*: un*.example.cominicial coincide con cualquier subdominio (incluidoa.b.example.com), pero no con el propio dominio raíz; unbedrock.*.amazonaws.comen una etiqueta intermedia coincide exactamente con una etiqueta (bedrock.us-east-1.amazonaws.com, nobedrock.evil.attacker.amazonaws.com). - La lista de permitidos se resuelve por sesión a partir de la línea base curada (
kBaselineAllowedDomains: proveedores de LLM, alojamiento de Git, registros de paquetes), más los dominios de GitHub (kGithubDomains), másSandboxSpec.egressAllowlist. La ruta de despacho nunca pasa entradas adicionales deegressAllowlist, así que en la práctica cada ejecución recibe la línea base más GitHub. - Una lista fija de denegados (
kBaselineDeniedDomains: endpoints de metadatos de la nube, sumideros de telemetría) prevalece sobre todas las permitidas. networkEnabled: falsesigue arrancando los proxies por sesión, pero la lista de permitidos está vacía, así que se rechaza toda conexión saliente. El despacho lo fija al arrancar la ejecución a partir de la regla Acceder a la red: denegar desactiva la red; permitir y preguntar primero la dejan activada.
SandboxSpec
Sección titulada «SandboxSpec»La especificación que se pasa a SandboxPort.launch:
| Campo | Tipo | Descripción |
|---|---|---|
sessionId |
String |
Identificador estable de la sesión (normalmente el id del espacio) |
workspaceId |
String |
Id del espacio de trabajo propietario |
agentId |
String? |
Agente vinculado actualmente al entorno aislado, si lo hay |
bindMounts |
List<SandboxBindMount> |
Montajes host→huésped; el entorno aislado solo ve las rutas del host que se enumeran aquí |
networkEnabled |
bool (predeterminado true) |
Lo fija el despacho a partir de la regla de salida a la red (desactivado solo cuando se resuelve como denegar). Cuando está desactivado, los proxies por sesión siguen arrancando, pero la lista de permitidos está vacía, así que se rechaza toda conexión saliente |
egressAllowlist |
List<String> (predeterminado []) |
Dominios de salida permitidos adicionales; se admiten comodines (*.example.com, más una forma intermedia de una sola etiqueta). El despacho nunca rellena este campo, así que una ejecución envuelta recibe la línea base curada más los dominios de GitHub |
guestWorkdir |
String? |
Directorio de trabajo predeterminado dentro del entorno aislado; cada llamada exec puede anularlo |
mode |
Mode (predeterminado chat) |
Define las reglas de escritura del sistema de archivos: chat mantiene los montajes bind escribibles; review, plan y orchestrate son de solo lectura |
protectedPaths |
List<String> (predeterminado []) |
Rutas del host que nunca deben ser escribibles dentro del entorno aislado, en ningún modo |
runnerStateDirs |
List<String> (predeterminado []) |
Directorios del host donde el runner guarda su propio estado, escribibles en todos los modos (el actual es un CLAUDE_CONFIG_DIR gestionado por Control Center) |
execGrantRoots |
List<String> (predeterminado []) |
Árboles de directorios aprobados por el operador que vuelven a abrir el bloqueo de exec en directorios escribibles en macOS. Linux los ignora: bwrap no tiene ningún bloqueo de exec en $HOME que reabrir |
protectedPaths contiene las copias de trabajo originales de los repositorios registrados, resueltas en cada despacho a partir de los repositorios del espacio de trabajo. Los agentes trabajan exclusivamente en worktrees de copia en escritura por conversación, así que los originales nunca deben ser escribibles desde dentro del entorno aislado: en macOS, el permiso general de escritura de Seatbelt sobre $HOME los dejaría si no escribibles a través de bash. Se suman al conjunto de denegación de escritura de secretos en todos los modos, chat incluido.
Cada ruta de lectura denegada y de escritura denegada se emite tanto en su forma literal como en su forma resuelta por enlaces simbólicos. El kernel compara una regla de denegación con la ruta resuelta, así que una regla escrita contra una ruta con enlaces simbólicos nunca se dispara; y en macOS ese es el caso habitual y no el exótico, ya que /tmp se resuelve a /private/tmp y /var/folders/… a /private/var/folders/…. Las entradas que contienen * o ? se tratan como globs y se dejan tal cual; una ruta que no se resuelve se conserva tal como se escribió.
SandboxBindMount
Sección titulada «SandboxBindMount»| Campo | Tipo | Descripción |
|---|---|---|
hostPath |
String |
Ruta absoluta en el host |
guestPath |
String |
Ruta dentro del entorno aislado (con el entorno aislado nativo es igual a hostPath; se conserva por simetría con los adaptadores) |
readOnly |
bool (predeterminado false) |
Monta en solo lectura cuando es true |
SandboxHandle
Sección titulada «SandboxHandle»Lo devuelve SandboxPort.launch:
| Campo | Tipo | Descripción |
|---|---|---|
sessionId |
String |
Identificador de la sesión |
backend |
SandboxBackend |
Qué backend está en ejecución |
state |
SandboxState |
Estado del ciclo de vida |
error |
Object? |
Se establece cuando state es error |
details |
Map<String, Object?> |
Contabilidad privada del adaptador (directorio de trabajo, PID, ruta del perfil, etc.) |
SandboxState
Sección titulada «SandboxState»| Estado | Descripción |
|---|---|
created |
Especificación creada, pero la VM aún no se ha iniciado |
warm |
En ejecución y lista para ejecutar comandos |
active |
Ejecutando un comando en este momento |
suspended |
En pausa o con checkpoint en disco para ahorrar RAM |
destroyed |
Desmontado; el handle ya no es válido |
error |
El lanzamiento falló; consulta SandboxHandle.error |
Eventos del entorno aislado
Sección titulada «Eventos del entorno aislado»| Tipo de evento | Descripción |
|---|---|
stdout |
Salida estándar del entorno aislado |
stderr |
Error estándar del entorno aislado |
exit |
El proceso del entorno aislado terminó (lleva exitCode) |
starting |
El entorno aislado se está iniciando |
ready |
El entorno aislado está listo para aceptar llamadas exec |
killed |
Proceso terminado por el host (OOM, tiempo de espera agotado, parada manual) |
violation |
Se ha infringido una política del entorno aislado (lleva un SandboxViolation) |
SandboxViolation
Sección titulada «SandboxViolation»| Campo | Tipo | Descripción |
|---|---|---|
action |
String |
El verbo denegado (p. ej. file-read*, network-outbound) |
target |
String |
Ruta o host que era el destino de la operación denegada |
raw |
String? |
Línea de registro sin procesar, útil para depurar |