Backends de sandbox
Resumen de backends
Sección titulada «Resumen de backends»| Backend | Valor | Plataforma | Disponibilidad |
|---|---|---|---|
| VM aislada | microvm |
macOS, Linux, Windows (hipervisor de microVM) | Condicionado por el sondeo del entorno de ejecución de microVM; se aplica a 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 |
| Ninguno | none |
Todas | El valor predeterminado al analizar la opción, el predeterminado del terminal y el valor al que se recurre cuando no hay ningún backend disponible o se establece --sandbox off |
SandboxBackend.fromName devuelve none para un valor almacenado nulo o no reconocido. Un "docker" almacenado se asigna a native.
microvm es el único backend con una frontera del kernel — la carga de
trabajo realmente no se ejecuta en el host. Nunca es una alternativa silenciosa
en ninguna dirección: pedirlo de forma explícita en un host que no puede
arrancar una VM falla de forma ruidosa («pedí una VM y obtuve mi computadora
portátil» es la única degradación que el recinto no puede permitirse), y solo un
valor predeterminado sin especificar desciende a native, con una línea de
registro que lo indica. El backend real de la sesión se informa de vuelta al
cliente y se marca con una insignia, así que un terminal nunca puede afirmar
estar dentro de un recinto mientras se ejecuta en el host. El ciclo de vida, las
imágenes y la salida de la propia VM se cubren en la
referencia de rigs.
Windows no tiene sandbox nativo. NativeSandboxAdapter.probe devuelve available: false en todos los host que no sean macOS o Linux/WSL2. Por lo tanto, el despacho de agentes en Windows usa none. El backend microvm es aparte: está condicionado por el sondeo del entorno de ejecución de microVM y se aplica a terminales interactivos y 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 sola vez, al arrancar el servidor.
| Host | available |
Nota o sugerencia |
|---|---|---|
| macOS | true |
sandbox-exec (Seatbelt) — aislamiento de espacios de nombres, sin frontera del kernel |
Linux o WSL2 con bwrap y socat |
true |
bubblewrap — aislamiento de espacios de nombres, sin frontera del kernel |
| Linux o WSL2 sin alguna de esas herramientas | false |
requiresInstall: true, con una sugerencia de instalación que nombra los paquetes faltantes |
| Cualquier otra plataforma | false |
El sandbox 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 sugerencia, o agent sandbox DISABLED by --sandbox off. GET /healthz no incluye ningún campo de sandbox.
--sandbox / CC_SERVER_SANDBOX acepta on (predeterminado) u off. Es una opción para desactivarlo, no para activarlo: on significa «envuelve cuando el host ofrece un backend», nunca «exige uno».
Backend nativo
Sección titulada «Backend nativo»macOS: Seatbelt
Sección titulada «macOS: Seatbelt»Usa el mecanismo de sandbox Seatbelt de Apple (el mismo sistema que utiliza el sandbox de apps de macOS).
El perfil generado es permisivo de forma predeterminada ((allow default)) y recorta denegaciones, porque un perfil totalmente de denegación por defecto vuelve inutilizable un shell interactivo: 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 checkouts registrados están protegidos por denegaciones explícitas de escritura y de renombrado, no por invisibilidad.
- Lecturas del sistema de archivos: se deniegan las rutas secretas (
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/Library/Keychainsy el resto del conjunto de denegación de lectura) - Escrituras del sistema de archivos: se restablecen a denegar y luego se permiten subrutas explícitas, con las rutas de denegación obligatoria (archivos rc del shell,
.git/hooks, la configuración de Claude, los checkouts protegidos) bloqueadas incluso dentro de una raíz escribible.file-write-unlinkse deniega en cada ruta denegada y en sus ancestros, así que un renombrado no puede eludir una denegación de escritura - Procesos: se deniega
process-execpara los binarios siempre peligrosos, además de un bloqueo a la ejecución de cualquier cosa desde un directorio escribible - Red: se restringe a los puertos del proxy en proceso más DNS; loopback no está permitido de forma general y los sockets Unix no están permitidos. 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), incluido en toda instalación de macOS: no se necesita 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 donde 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 socket 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 montaje bind escribible. La
política de despacho estándar exige estas denegaciones por glob de nombre de
archivo, así que el despacho nativo de agentes actualmente
falla cerrado en Linux/WSL2 incluso cuando el sondeo encuentra bubblewrap. No
se ejecuta con una política silenciosamente más débil. Se necesita un backend
con reglas de nombre de archivo en el momento de la creación para restaurar el
despacho nativo en Linux. Deshabilitar el sandbox es una opción explícita y sin
confinamiento, no un rodeo equivalente.
Backend sin sandbox
Sección titulada «Backend sin sandbox»Sin sandbox. El proceso se ejecuta directamente en el host con el acceso del host al sistema de archivos, la red y los procesos. ACP y la herramienta bash del arnés siguen recibiendo saneamiento del entorno 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 somete a sandbox según sus propias reglas, no según 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 a menos que el cliente pida native de forma explícita; 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 con 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 aplican: son competencia del despacho. Si la envoltura no es compatible, la sesión falla en lugar de mostrar una insignia de nativo en un PTY del shell del host.
Salida de red
Sección titulada «Salida de red»Cuando se lanza un sandbox, el acceso saliente a la red lo aplican proxies en proceso, no reglas de firewall del kernel. En un host sin ningún backend disponible nada de esto aplica, y un proceso lanzado llega a la red exactamente como lo haría el usuario del servidor.
- El entorno de ejecución del sandbox levanta 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 en sandbox reciben variables de entorno de proxy (
HTTP_PROXY/HTTPS_PROXY→ el proxy HTTP,ALL_PROXY→ el proxy SOCKS;GIT_SSH_COMMANDenruta git sobre 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 sandbox comparte el loopback del host y se comunica con ellos directamente. - El host de destino de cada conexión se compara con la lista de permitidos de dominios de la sesión; cualquier otra cosa se deniega. Hay dos formas de comodín, cada una con exactamente un
*: una al principio,*.example.com, coincide con cualquier subdominio (incluidoa.b.example.com) pero no con el dominio raíz; una en una etiqueta intermedia,bedrock.*.amazonaws.com, coincide con exactamente 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 denegación (
kBaselineDeniedDomains: endpoints de metadatos de la nube, sumideros de telemetría) prevalece sobre todos los permisos. networkEnabled: falseigualmente arranca 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 sesión (normalmente el id del espacio) |
workspaceId |
String |
Id del espacio de trabajo propietario |
agentId |
String? |
Agente vinculado actualmente al sandbox, si lo hay |
bindMounts |
List<SandboxBindMount> |
Montajes host→huésped; el sandbox 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 adicionales permitidos; se admiten comodines (*.example.com, además de una forma intermedia de una sola etiqueta). El despacho nunca rellena esto, 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 sandbox; cada llamada exec puede sobrescribirlo |
mode |
Mode (predeterminado chat) |
Define las reglas de escritura del sistema de archivos: chat mantiene escribibles los montajes bind; review, plan y orchestrate son de solo lectura |
protectedPaths |
List<String> (predeterminado []) |
Rutas del host que nunca deben ser escribibles dentro del sandbox, 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 administrado por Control Center) |
execGrantRoots |
List<String> (predeterminado []) |
Árboles de directorios aprobados por el operador que reabren el bloqueo de exec de directorios escribibles en macOS. Linux los ignora: bwrap no tiene ningún bloqueo de exec de $HOME que reabrir |
protectedPaths contiene los checkouts originales de los repos registrados, resueltos en cada despacho a partir de los repos 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 sandbox; en macOS, el permiso de escritura general que Seatbelt concede a $HOME los dejaría, de lo contrario, escribibles por medio de bash. Se suman al conjunto de denegación de escritura de secretos en todos los modos, incluido chat.
Cada ruta de denegación de lectura y de escritura 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 activa, y en macOS ese es el caso habitual y no el exótico, ya que /tmp se resuelve como /private/tmp y /var/folders/… como /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 sandbox (con el sandbox nativo es igual a hostPath; se conserva por simetría entre adaptadores) |
readOnly |
bool (predeterminado false) |
Se monta en solo lectura cuando es true |
SandboxHandle
Sección titulada «SandboxHandle»Lo devuelve SandboxPort.launch:
| Campo | Tipo | Descripción |
|---|---|---|
sessionId |
String |
Identificador de sesión |
backend |
SandboxBackend |
Qué backend se está ejecutando |
state |
SandboxState |
Estado del ciclo de vida |
error |
Object? |
Se establece cuando state es error |
details |
Map<String, Object?> |
Registro interno del adaptador (directorio de trabajo, PID, ruta del perfil, etc.) |
SandboxState
Sección titulada «SandboxState»| Estado | Descripción |
|---|---|
created |
La especificación se creó, pero la VM aún no ha arrancado |
warm |
En ejecución y lista para ejecutar comandos |
active |
Ejecutando un comando en este momento |
suspended |
En pausa o con punto de control en disco para ahorrar RAM |
destroyed |
Desmontado; el handle ya no es válido |
error |
El lanzamiento falló; consulta SandboxHandle.error |
Eventos del sandbox
Sección titulada «Eventos del sandbox»| Tipo de evento | Descripción |
|---|---|
stdout |
Salida estándar del sandbox |
stderr |
Error estándar del sandbox |
exit |
El proceso del sandbox terminó (incluye exitCode) |
starting |
El sandbox está arrancando |
ready |
El sandbox está listo para aceptar llamadas exec |
killed |
El host mató el proceso (OOM, tiempo de espera agotado, detención manual) |
violation |
Se infringió una política del sandbox (incluye 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 fue el destino de la operación denegada |
raw |
String? |
Línea de registro sin procesar, útil para la depuración |
Ver también
Sección titulada «Ver también»- Sandbox y seguridad
- Configurar políticas de sandbox
- Barandillas
- CLI de cc_server: el flag
--sandbox