Ejecución de código en entorno aislado
El crate adk-sandbox proporciona ejecución de código aislada para agentes ADK, con dos niveles de aislamiento:
- Aislamiento de procesos — procesos secundarios con aislamiento del entorno y aplicación de tiempos de espera
- Perfiles de sandbox a nivel del sistema operativo — restricciones a nivel del kernel sobre el sistema de archivos, la red y la creación de procesos
Motores
| Backend | Nivel de aislamiento | Lenguajes | Indicador de funcionalidad |
|---|---|---|---|
ProcessBackend | Entorno + tiempo de espera | Rust, Python, JS, TS, Comando | process (predeterminado) |
ProcessBackend + sandbox | Nivel del kernel | Igual que arriba | process + sandbox-native |
WasmBackend | Completo (memoria, sistema de archivos, red) | solo WASM | wasm |
¿Qué aislamiento estás obteniendo?
ProcessBackend::isolation() lo informa, por lo que esto no es algo que deba inferirse del nombre del crate:
| Resultado | Significado |
|---|---|
IsolationClass::SubprocessOnly | Un proceso hijo con el entorno borrado, un tiempo de espera y su propio grupo de procesos. El sistema operativo no aplica ninguna restricción adicional: el código puede leer el sistema de archivos del host y acceder a la red. Esto es lo que proporciona ProcessBackend::default(). |
IsolationClass::OsEnforced | Se adjuntan un aplicador y una política, por lo que el sistema operativo restringe el proceso hijo. |
Dos aspectos del backend de procesos que conviene conocer:
- Los programas se resuelven antes de borrar el entorno. Un
python3,nodeorustcsin ruta se busca en elPATHde quien realiza la llamada y se pasa al proceso hijo como una ruta absoluta. Esto significa que el proceso hijo no necesita su propioPATHpara iniciarse; anteriormente, quien realizaba la llamada tenía que incluirPATHenExecRequest::env, lo que también permitía al código ejecutado generar cualquier otra cosa desde allí. - La compilación pasa por el mismo límite que la ejecución. El código fuente de Rust solía
compilarse mediante un comando creado fuera de la ruta compartida, por lo que la compilación no tenía un envoltorio de cumplimiento, ni tiempo de espera, ni grupo de procesos. Esto es importante porque la compilación no es inerte:
include_str!lee archivos y las macros procedurales ejecutan código arbitrario antes de que exista el binario generado. La fase de compilación recibe una lista de herramientas permitidas específica de la plataforma; en Windows, esto incluye las rutas de MSVC y Windows SDK, detectadas a partir de la cadena de herramientas instalada cuando quien realiza la llamada no se encuentra ya en un shell de Developer. La compilación utiliza el enlazadorrust-lldde la cadena de herramientas de Rust, por lo que no se puede seleccionar unlink.exeno relacionado que aparezca antes enPATH. Un mecanismo de cumplimiento del sistema operativo es lo que restringe esa fase.
Prioridad del entorno
SandboxPolicy::env proporciona valores predeterminados para cada ejecución y ExecRequest::env
los anula por llamada. Las variables de la política se ignoraban por completo anteriormente.
Perfiles de aislamiento del sistema operativo
El cumplimiento del aislamiento a nivel del sistema operativo restringe los procesos hijos a nivel del kernel. Esto va más allá del aislamiento del entorno: el propio sistema operativo bloquea el acceso no autorizado al sistema de archivos, las conexiones de red y la creación de procesos.
Compatibilidad con plataformas
| Plataforma | Aplicador | Cómo funciona |
|---|---|---|
| macOS | Seatbelt (sandbox-exec) | Reglas a nivel de llamadas al sistema: «permitir de forma predeterminada, denegar lo peligroso» — deniega escrituras, red y bifurcaciones; las lecturas no están restringidas |
| Linux | bubblewrap (bwrap) | Aislamiento del espacio de nombres del sistema de archivos (montajes en lista blanca) |
| Windows | AppContainer | No implementado — el enforcer informa que no está disponible |
Inicio rápido
use adk_sandbox::{
ProcessBackend, ProcessConfig, SandboxBackend,
SandboxPolicyBuilder, get_enforcer,
};
// 1. Define what the sandboxed process can do
let policy = SandboxPolicyBuilder::new()
.allow_read("/usr") // Read system libraries
.allow_read_write("/tmp/work") // Write to work directory
.allow_process_spawn() // Python needs to exec
// Network is denied by default
.env("PATH", "/usr/bin:/usr/local/bin")
.build();
// 2. Get the platform-appropriate enforcer
let enforcer = get_enforcer()?;
// 3. Create a sandboxed backend
let backend = ProcessBackend::with_sandbox(
ProcessConfig::default(),
enforcer,
policy,
);
// 4. Execute code — network is blocked, writes restricted
let result = backend.execute(request).await?;
Indicadores de funciones
[dependencies]
# Auto-detect platform enforcer
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-native"] }
# Or pick a specific platform
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-macos"] }
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-linux"] }
SandboxPolicy
La política define lo que un proceso aislado puede hacer:
| Campo | Predeterminado | Descripción |
|---|---|---|
allowed_paths | [] (denegar todo) | Rutas del sistema de archivos con acceso de solo lectura o de lectura y escritura |
allow_network | false | Si se permite el acceso a la red |
allow_process_spawn | false | Si se permite la creación de procesos secundarios |
env | {} | Variables de entorno para el proceso aislado |
Diferencias entre plataformas
macOS (Seatbelt): Utiliza «permitir de forma predeterminada, denegar lo peligroso»: comienza con acceso total y luego bloquea la red, las escrituras de archivos y la creación de procesos. Un enfoque de lista blanca pura no funciona porque Python necesita decenas de categorías de llamadas al sistema específicas de macOS durante el inicio.
Linux (bubblewrap): Utiliza una lista blanca basada en espacios de nombres: de forma predeterminada no existe nada; solo se monta lo necesario. Instala con apt install bubblewrap o dnf install bubblewrap.
Windows (AppContainer): No está implementado. El diseño se basa en ACL con tokens: un SID restringido sin acceso de forma predeterminada y, posteriormente, ACL otorgadas para rutas específicas; pero faltan la creación de contenedores, las ACL, las capacidades y la limpieza de objetos de trabajo, por lo que probe() devuelve EnforcerUnavailable. Ejecuta sin un aplicador de restricciones en Windows, o utiliza macOS o Linux, donde la aplicación de restricciones es real.
Ejemplo
Consulta examples/sandbox_agent/ para ver un ejemplo completo basado en LLM-agent que ejecuta código Python en un entorno aislado, con el acceso a la red bloqueado por el kernel del sistema operativo.