Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Aislamiento

El runtime puede envolver las invocaciones de herramientas en un sandbox a nivel de sistema operativo que restringe el acceso al sistema de archivos al workspace y elimina el acceso a los secrets del proceso padre. Esto es distinto del sistema de autonomía y de la lista de permitidos de comandos: estas son capas de política que deciden si una herramienta puede ejecutarse; el sandbox es una capa de mecanismo que confina lo que una herramienta en ejecución puede alcanzar si efectivamente se ejecuta.

La configuración del sandbox se encuentra en un perfil de riesgo. Cada agente apunta a un perfil de riesgo mediante agents.<alias>.risk_profile; el sandbox enable/backend del agente se lee de ese perfil.

Proveedores de modelos de CLI (por ejemplo grok_cli): la CLI externa queda fuera del flujo nativo de aprobación de herramientas de ZeroClaw. El aislamiento mediante sandbox del perfil de riesgo anterior no la confina. Por lo tanto, el proveedor ACP grok_cli inyecta --sandbox strict, --permission-mode dontAsk y un conjunto vacío de herramientas integradas de forma predeterminada, y rechaza las solicitudes de permisos de ACP (seleccionando reject_once cuando la CLI lo ofrece; de lo contrario, cancela la solicitud). En cambio, las opciones explícitas de omisión del alias extra_args seleccionan la opción allow_once de la solicitud; esto no deshabilita el sandbox activo del sistema operativo de Grok ni anula sus reglas de denegación. Los demás modos de permiso siguen funcionando con denegación por defecto. Consulta Catálogo → Grok Build CLI.

sandbox_enabled = false (o sandbox_backend = "none") deshabilita el envoltorio adicional de sandbox a nivel del sistema operativo del perfil. En el entorno de ejecución nativo, las herramientas quedan sin un sandbox a nivel del sistema operativo. Con [runtime] kind = "docker", el entorno de ejecución de Docker sigue siendo el límite del contenedor y se informa como docker-runtime; estas opciones impiden que un segundo contenedor de sandbox envuelva el docker run propio del entorno de ejecución. Consulta el Ejemplo mínimo funcional canónico para ver cómo se integra un perfil de riesgo en el resto de la configuración.

Detección automática

sandbox_backend = "auto" resuelve un backend cuando se crea el sandbox. El orden depende de la plataforma, de las funciones de sandbox con las que se compiló el binario y del tipo de runtime:

PlataformaOrden probada
LinuxLandlock (solo cuando se compila con sandbox-landlock) → Firejail
macOSBubblewrap (solo cuando se compila con sandbox-bubblewrap) → Seatbelt (sandbox-exec)
WindowsSin backend a nivel de sistema operativo

Bubblewrap no está en la cadena de autodetección de Linux; solo se puede acceder a él nombrándolo explícitamente. Landlock y Bubblewrap son funciones de tiempo de compilación, y una compilación que no habilita una de ellas omite por completo ese backend. Ninguna de estas funciones está en el conjunto default ni en el conjunto dist que usa la compilación de lanzamiento, por lo que una compilación estándar inicia la lista de Linux con Firejail y la lista de macOS con Seatbelt.

Tras la lista de plataformas, auto intenta usar Docker solo cuando el tipo de runtime no es native ni docker. Docker no forma parte del mecanismo de fallback automático del runtime nativo: con [runtime] kind = "native" (el valor predeterminado), auto nunca selecciona Docker, incluso cuando el daemon es accesible. Docker también se omite cuando el runtime ya es docker, porque el contenedor del runtime es el límite. El único otro tipo de runtime, cloudflare, es rechazado por create_runtime en crates/zeroclaw-config/src/platform/mod.rs por no estar implementado, por lo que, en una configuración ejecutable, auto nunca llega al backend de Docker.

Cuando ninguna de las opciones de la lista está disponible, la selección termina en none en el entorno de ejecución nativo: ningún sandbox a nivel de sistema operativo envuelve las llamadas a herramientas, y solo se aplica la seguridad de la capa de aplicación descrita anteriormente. En el entorno de ejecución Docker, en cambio, la selección termina en docker-runtime, que mantiene el límite del contenedor sin un segundo envoltorio de sandbox.

Nombrar un backend explícitamente no recorre esta lista. Si el backend solicitado no está compilado, no funciona en la plataforma, no es compatible con el tipo de runtime o falla su sonda de disponibilidad, la selección pasa directamente a none (nativo) o docker-runtime (runtime de Docker), en lugar de pasar al siguiente backend.

Para forzar un backend específico, establece sandbox_backend con el nombre de un backend: landlock, firejail, bubblewrap, docker, sandbox-exec o none.

Lo que el sandbox confina

Acceso a archivos

  • Acceso de lectura: restringido al espacio de trabajo, /usr, /lib, /etc (solo lectura) y las rutas adicionales listadas explícitamente.
  • Acceso de escritura: restringido al espacio de trabajo y a /tmp.
  • Rutas prohibidas: reglas de prefijo de componentes absolutos de [risk_profiles.<alias>].forbidden_paths. Los prefijos de autorización y denegación en conflicto utilizan la precedencia de la coincidencia más específica, y la denegación prevalece en caso de empate; consulta Reglas de rutas de autonomía.

Red

El acceso a la red depende de cada backend, y la mayoría no lo modifica:

  • Landlock controla únicamente el acceso al sistema de archivos, por lo que el tráfico de red saliente no cambia.
  • Firejail se ejecuta con --noprofile y sin opciones de red, por lo que tampoco modifica el acceso a la red.
  • Bubblewrap se ejecuta con --unshare-all y nunca con --share-net, por lo que el sandbox no tiene acceso a la red.
  • Seatbelt deniega por defecto el tráfico de red saliente y solo permite la resolución DNS a través de /var/run/mDNSResponder y las conexiones a localhost.
  • Docker pasa --network none para el backend de sandbox docker; el runtime de Docker pasa [runtime.docker].network, que por defecto es none.

Las restricciones de red específicas de cada herramienta (browser, HTTP, web_fetch) se definen en los bloques de configuración propios de esas herramientas ([browser].allowed_domains, [http_request].allowed_domains, [web_fetch].allowed_domains).

Para http_request, los destinos privados/locales permanecen bloqueados de forma predeterminada. Use [http_request].allowed_private_hosts para permitir solo hosts privados/locales específicos como localhost o 10.0.0.1 mientras mantiene [http_request].allowed_domains no vacío; allowed_domains = [] sigue deshabilitando las solicitudes. La configuración existente [http_request].allow_private_hosts = true sigue siendo una opción de compatibilidad más amplia.

Entorno

El sandbox solo deja pasar las variables de entorno indicadas en [risk_profiles.<alias>].shell_env_passthrough. Los secretos heredados no llegan a las herramientas en sandbox a menos que se pasen explícitamente.

Límites de procesos

Los tiempos de espera de tiempo real por herramienta residen en el bloque de configuración propio de la herramienta ([shell_tool].timeout_secs, etc.). Los límites específicos de Docker (memoria, CPU) residen en [runtime.docker] cuando el tipo de runtime del agente está configurado como docker:

Binario de shell

Cuando [runtime].shell no está definido, el runtime nativo detecta un valor predeterminado según la plataforma. En Windows intenta pwsh, luego powershell y después cmd.exe. En macOS primero usa el shell de inicio de sesión del usuario actual según passwd y luego intenta zsh, bash y /bin/sh. En Linux primero usa el shell de inicio de sesión según passwd y luego intenta bash, zsh y /bin/sh. Android se mantiene fijado a /system/bin/sh. Establezca [runtime].shell para elegir un intérprete explícitamente:

[runtime]
shell = "bash"      # resuelve mediante PATH, o usa una ruta absoluta

En Unix, los shells compatibles con POSIX se invocan como <shell> -c "<command>". powershell/pwsh seleccionan la sintaxis y la política de PowerShell en todos los hosts de escritorio compatibles y se ejecutan como <interpreter> -NoProfile -NonInteractive -Command <command>, de modo que los scripts de perfil no pueden redefinir comandos saltándose la política y los avisos no pueden bloquear la ejecución. El valor debe ser un nombre de comando simple que se encuentre en PATH (p. ej. "bash" o "pwsh") o una ruta absoluta a un ejecutable (p. ej. "/bin/bash"); la validación de la configuración rechaza valores vacíos y rutas relativas con separadores (p. ej. "./sh", "bin/sh"). Antes de lanzar el proceso, ZeroClaw canonicaliza directamente una ruta de shell absoluta y resuelve un nombre simple frente al PATH efectivo cuando se proporciona uno; una fábrica de runtime puede resolver y conservar antes ese lanzador canónico, mientras que las demás rutas usan la resolución conservada o la del entorno durante la preparación del comando. El destino debe ser un archivo ejecutable regular, y cualquier fallo devuelve un error desde la construcción del runtime o la preparación del comando, antes de la ejecución. La configuración explícita tiene prioridad sobre la detección por defecto. En Unix, la búsqueda del shell de inicio de sesión usa getpwuid_r; si falla o indica un ejecutable no disponible, se usa el orden de respaldo de la plataforma. Si un PATH inyectado omite un valor por defecto de nombre simple seleccionado, la preparación falla en lugar de cambiar de intérprete.

Firejail, Bubblewrap y macOS Seatbelt sustituyen el comando del host por un lanzador de sandbox. Cuando la identidad de shell solicitada difiere de la ruta canónica del ejecutable, el wrapper debe conservar esa identidad (por ejemplo, sh seleccionando un applet de BusyBox o el modo de compatibilidad de Bash) mientras ejecuta el destino canónico validado. En Linux, Firejail y Bubblewrap requieren un env o genv compatible con GNU y con soporte para --argv0 en las entradas absolutas de PATH del proceso host. ZeroClaw sondea cada candidato durante hasta dos segundos; el helper y sus bibliotecas deben ser accesibles dentro del sandbox. En macOS, Seatbelt usa el /bin/bash del sistema con un trampolín exec -a fijo, por lo que no se requiere una instalación separada de GNU coreutils. El trampolín pasa la identidad solicitada y los argumentos del comando como argumentos de proceso, no como código de shell interpolado. ZeroClaw no amplía el acceso al sistema de archivos ni recurre a un comando sin sandbox cuando un helper requerido no puede ejecutarse. La búsqueda del helper del host en Linux no usa la superposición de entorno exclusiva de la TUI.

Para estos lanzamientos envueltos que preservan la identidad, las rutas canónicas de shell que contienen = siguen rechazadas; en Linux, env interpretaría dichos operandos como asignaciones de variables de entorno. Las rutas de helpers en Linux que contienen = también se rechazan por el mismo motivo, y los helpers ausentes o no compatibles producen un error de preparación. La ejecución nativa directa, Landlock y la selección de shell independiente de Docker dentro del contenedor no requieren un helper de identidad en el host.

En Windows, el valor selecciona la familia de intérpretes según el nombre de su archivo:

[runtime]
shell = "pwsh"        # PowerShell 7+   -> pwsh -NoProfile -NonInteractive -Command <cmd>
# shell = "powershell"  # Windows PowerShell 5.x
# shell = "cmd"         # cmd.exe /C "<cmd>" explícito

powershell y pwsh (como nombre simple resuelto mediante PATH, o como ruta absoluta, por ejemplo "C:\\Program Files\\PowerShell\\7\\pwsh.exe") se ejecutan a través de PowerShell; cualquier otro valor explícito se ejecuta a través de cmd.exe /C, como en el comportamiento histórico. En Windows, solo se rechaza un valor vacío o formado únicamente por espacios en blanco; el intérprete se localiza en el momento de crear el proceso.

La herramienta de shell, las herramientas de habilidades respaldadas por shell y las tareas de shell de cron/programadas usan esta selección del tiempo de ejecución. El tiempo de ejecución también comunica el dialecto del shell a la política de seguridad, por lo que la política valida el mismo lenguaje que ejecutará el comando.

Al modelo se le comunica la misma selección del entorno de ejecución. La línea ## Runtime del prompt del sistema contiene un campo Shell: que indica el intérprete configurado (bash, zsh, pwsh, powershell, cmd) y, cuando una herramienta registrada acepta un comando escrito por el modelo (shell, cron_add, cron_update, schedule), una sección ## Shell enumera las formas de comando que acepta ese dialecto, de modo que el modelo escribe Get-ChildItem con PowerShell y dir /a con cmd.exe, en lugar de adivinarlo a partir del nombre del sistema operativo. Ambos proceden del mismo adaptador que construye el comando, por lo que el shell indicado no puede diferir del que se ejecuta. Los entornos de ejecución sin acceso al shell (como WASM) omiten ambos. Las recomendaciones de eliminación de la sección de seguridad también siguen el dialecto: solo se sugiere trash donde existe.

La política de PowerShell acepta una gramática acotada: invocaciones de comandos simples, argumentos sin comillas o entre comillas y canalizaciones. Las lecturas de variables simples, como $PSHOME y $PSVersionTable.PSVersion, se limitan a un comando independiente Write-Output/echo, de modo que no puedan ocultar rutas del sistema de archivos a los comandos posteriores. Las expresiones y las formas alternativas de invocación, incluidas las subexpresiones, los paréntesis, los bloques de script, los literales de tipo/las llamadas a métodos estáticos, los operadores de llamada, la redirección, los separadores de instrucciones, las secuencias de escape con acento grave, las variables con ámbito como $env:NAME, las rutas de proveedores de PowerShell, la ejecución directa de scripts y los intérpretes de comandos anidados, se clasifican como de alto riesgo. Los nombres de comandos exclusivos de PowerShell no se añaden a la lista de permitidos predeterminada entre dialectos; añade los cmdlets que necesites a allowed_commands, o habilita "*" con la aprobación correspondiente y la configuración de alto riesgo. Los cmdlets de mutación conocidos siguen los controles de aprobación de riesgo medio/alto; los comandos independientes desconocidos y los cmdlets Verb-Noun son de alto riesgo de forma predeterminada.

Los trabajos de shell de Cron heredan el límite global del entorno de ejecución tanto durante la validación como durante la ejecución. Los trabajos nativos usan el shell nativo configurado, mientras que los trabajos de Docker se ejecutan mediante la imagen, el montaje, la red y la configuración de CPU, memoria y raíz de solo lectura configurados. Una fila de cron almacena el comando, no una copia del entorno de ejecución ni del dialecto. Por lo tanto, después de que una recarga del demonio vuelva a crear el planificador y el registro de herramientas, los trabajos existentes usan la configuración [runtime] recién cargada en su siguiente ejecución. Las ejecuciones programadas de cron se vuelven a validar y nunca se preautorizan.

Solo se aplica al tipo de tiempo de ejecución nativo. Docker usa el shell de su contenedor, y Android (siempre /system/bin/sh) ignora la configuración y no la valida.

Notas por backend

Landlock

La ruta nativa de Linux. Sin configuración, aplicada por el kernel, con una sobrecarga muy baja. Requiere el kernel 5.13 o posterior.

Limitaciones:

  • Sin confinamiento de red: Landlock solo controla el acceso al sistema de archivos.
  • forbidden_paths se aplica mediante reglas basadas en rutas, no en inodos, por lo que un enlace simbólico ingenioso a veces puede eludirlo (resolvemos los enlaces antes de pasarlos a Landlock para mitigar esto).

Bubblewrap (bwrap)

Sandbox basado en espacios de nombres de usuario de Flatpak. Restringe el sistema de archivos y se ejecuta sin acceso a la red. Requiere tener bubblewrap instalado.

Debian/Ubuntu

sudo apt install bubblewrap

Arch

sudo pacman -S bubblewrap

Fedora

sudo dnf install bubblewrap

Firejail

Sandbox basado en SUID. Más antiguo pero ampliamente disponible.

sh

sudo apt install firejail

Firejail con su perfil predeterminado es bastante permisivo, y ZeroClaw lo omite con --noprofile, pasando en su lugar un conjunto explícito de opciones.

Docker

Funciona en cualquier lugar donde funcione Docker. El tipo de runtime Docker ([runtime] kind = "docker") ejecuta cada invocación de shell en un contenedor efímero; consulte el bloque [runtime.docker] de arriba para los controles de imagen y recursos. git_operations no se ejecuta dentro de ese contenedor: los comandos de Git clasificados como de escritura se rechazan para el runtime Docker, mientras que los comandos clasificados como de lectura conservan su aislamiento de lectura existente en el host. Use la herramienta de shell para los comandos de Git que deben ejecutarse dentro del contenedor.

sh

docker build -t zeroclaw-sandbox:local dev/sandbox/   # compilar la imagen del kit de herramientas integrado

Ventajas: fuerte aislamiento, funciona en cualquier sistema operativo. Desventajas: costo de inicio del contenedor por invocación (100–500 ms). Ideal para implementaciones en producción donde la sobrecarga es aceptable.

Cinturón de seguridad (macOS)

Sandbox nativo de macOS (sandbox-exec). Los perfiles son SBPL: ZeroClaw incluye uno para ejecuciones de herramientas. Funciona en macOS 10.11+.

Limitación: algunas herramientas de CLI (versiones antiguas de git, algunos binarios enlazados con Homebrew) no cooperan con las reglas de acceso a archivos de Seatbelt. Si ve errores de “Operation not permitted” en las llamadas al shell del agente en macOS, la herramienta necesita un acceso más amplio al sistema de archivos: considere cambiar a Docker.

none

Sin sandboxing. Las herramientas se ejecutan con todos los privilegios del usuario del servicio ZeroClaw. Esto es lo que habilita el modo YOLO. Ruidoso, obvio e intencional.

Solución de problemas

  • No hay ningún sandbox activo: revise zeroclaw service status y el journal. La selección registra el backend que finalmente eligió (“Landlock sandbox enabled (Linux kernel 5.13+)”, “No sandbox backend available, using application-layer security”), y un backend solicitado explícitamente que no está disponible emite una advertencia con su nombre (“Firejail requested but not available, falling back to application-layer”). El registro indica el resultado, no todos los backends que se probaron.
  • Las herramientas funcionan en desarrollo, pero fallan en el servicio: el usuario del servicio a menudo difiere del usuario de la CLI. Verifique que ambos tengan los permisos relacionados con el sandbox que sean necesarios (Landlock: ninguno; Bubblewrap: userns habilitado; Docker: usuario del servicio en el grupo docker).
  • Invocaciones lentas de herramientas en el runtime de Docker: la primera invocación descarga la imagen, las siguientes son rápidas. Descargue previamente con docker pull <image>.

Referencia de código

  • Detección: crates/zeroclaw-runtime/src/security/detect.rs
  • Backends: crates/zeroclaw-runtime/src/security/ (landlock.rs, firejail.rs, bubblewrap.rs, docker.rs, seatbelt.rs)
  • Esquema: RiskProfileConfig y DockerRuntimeConfig en crates/zeroclaw-config/src/schema.rs