Implementación de un sandbox seguro para agentes locales

Los agentes de código están mejorando mucho en la ejecución de comandos de terminal para explorar el entorno y realizar cambios. Los usuarios que aprueban automáticamente estos comandos desbloquean agentes significativamente más potentes, pero a costa de un mayor riesgo. Un agente que se equivoca puede borrar bases de datos, desplegar código defectuoso o filtrar secretos.
Exigir aprobación humana para cada comando mitiga ese riesgo, pero a menudo solo de forma temporal. A medida que se acumulan las aprobaciones, los usuarios dejan de revisarlas con cuidado. Esto empeora cuando los ingenieros ejecutan varios agentes en paralelo y tienen que cambiar de contexto entre solicitudes de aprobación. El resultado es fatiga de aprobación, lo que socava el propósito de las aprobaciones en primer lugar.
En los últimos tres meses hemos abordado esto desplegando sandboxing para agentes en macOS, Linux y Windows. Los agentes en sandbox se ejecutan libremente dentro de un entorno controlado y solo solicitan aprobación cuando necesitan salir de él, normalmente para acceder a internet.
Esto reduce las interrupciones de forma drástica. Los agentes en sandbox se detienen un 40% menos a menudo que los que no están en sandbox, lo que ahorra a los usuarios horas de revisión y aprobación manual.


Nuestros objetivos con el sandbox
Comenzamos nuestro trabajo de sandboxing con el objetivo de eliminar interrupciones mientras mejorábamos la seguridad. Queríamos proporcionar a los agentes suficiente margen de maniobra para ser efectivos, y al mismo tiempo denegarles permisos que implicaran riesgos.
Encontrar este equilibrio es más difícil de lo que parece. Muchos comandos de terminal requieren privilegios inesperados, incluso para pasos básicos de prueba o compilación. Un sandbox ingenuo los bloquearía y rompería el flujo de trabajo del agente. Diseñar un sandbox práctico es un ejercicio de equilibrar las compensaciones entre seguridad y usabilidad, trabajando dentro de los parámetros establecidos por cada sistema operativo.
Implementación
Ofrecemos una API de sandbox unificada, con implementaciones específicas para cada plataforma. macOS, Linux y Windows proporcionan primitivas de aislamiento distintas que han guiado las decisiones de diseño subyacentes.
macOS
Evaluamos cuatro enfoques de sandboxing en macOS: App Sandbox, contenedores, máquinas virtuales y Seatbelt. App Sandbox está diseñado para la Mac App Store y requeriría que Cursor firme cada binario que un agente pudiera ejecutar. Esto habría añadido una complejidad significativa y habría abierto nuevos vectores de abuso al permitir que los binarios generados o modificados por agentes heredaran la confianza de Cursor. Los contenedores nos limitarían a binarios de Linux y las máquinas virtuales imponen una latencia de arranque inaceptable y una sobrecarga de memoria considerable.
Esto nos dejó con Seatbelt, al que se accede mediante sandbox-exec. Se introdujo en 2007 y se declaró obsoleto en 2016, pero todavía lo usan aplicaciones críticas de terceros como Chrome. Permite ejecutar un comando bajo un perfil de sandbox que restringe el comportamiento de todo un árbol de subprocesos.
El perfil define permisos con gran granularidad, restringiendo syscalls y lecturas o escrituras en archivos y directorios específicos mediante un lenguaje de políticas idiosincrático. Generamos esta política dinámicamente en tiempo de ejecución según la configuración a nivel de espacio de trabajo y a nivel de administrador, junto con el .cursorignore del usuario.
(deny file-write* (regex "^.*\/\\\.vscode($|\/.*)")
)
(deny file-write* (require-all
(regex "^.*\/\\\.cursor($|\/.*)")
(require-not (regex "^.*\/\\\.cursor/(rules|commands|worktrees|skills|agents)($|\/.*)")))
)
(deny file-write* (regex "^.*\\\.code-workspace$"))
(deny file-write* (regex "^.*\/\\\.cursorignore$"))
(deny file-write* (regex "^.*\/\\\.git/config$"))
(deny file-write* (regex "^.*\/\\\.git/hooks($|\/.*)")
)
(deny file-write* (regex "^(/private)?/var/folders/.*-cursor(-[a-z]+)?-zsh($|\/.*)")
)
Linux
Linux es a la vez más fácil y más difícil que macOS. El kernel expone las primitivas necesarias a través de Landlock y seccomp, pero el espacio de usuario es responsable de combinarlas en un sandbox utilizable. Aunque varios proyectos de código abierto combinan estos mecanismos de forma eficaz, ninguno admite funciones como .cursorignore.
Decidimos usar Landlock y seccomp directamente. Seccomp bloquea las llamadas al sistema no seguras, mientras que Landlock aplica restricciones al sistema de archivos, lo que nos permite hacer que los archivos ignorados sean completamente inaccesibles para el proceso aislado (sandboxed). Asignamos los espacios de trabajo de los usuarios a un sistema de archivos superpuesto (overlay filesystem) y sobrescribimos los archivos ignorados con copias protegidas por Landlock que no se pueden leer ni modificar.
Encontrar y volver a montar estos archivos es la parte más lenta del sandboxing en Linux. Sería más sencillo filtrar de forma diferida las operaciones del sistema de archivos como hace macOS, pero Linux no proporciona un acceso sencillo a la ruta del archivo en un contexto seccomp-bpf.
Windows
En Windows, ejecutamos nuestro sandbox de Linux dentro de WSL2. Crear un sandbox nativo equivalente en Windows es considerablemente más difícil porque la mayoría de las primitivas de aislamiento existentes están pensadas para navegadores y no admiten herramientas de desarrollo de propósito general. Estamos trabajando con Microsoft para garantizar que las primitivas necesarias estén disponibles.
Enseñar a los agentes a usar el sandbox
Un sandbox solo es efectivo si los agentes pueden anticipar qué comandos tendrán éxito dentro del sandbox y reconocer cuándo es necesaria una escalada de permisos. Conseguir que los modelos fueran conscientes del sandbox requirió cambios en la infraestructura del agente.
Comenzamos actualizando las descripciones de la herramienta Shell para explicar las restricciones del sandbox: si los comandos se ejecutan con acceso al sistema de archivos, a git o a la red según la configuración del usuario, y cómo el agente puede solicitar permisos elevados cuando sea necesario. Lograr una modificación básica de la infraestructura con la que quedáramos satisfechos requirió muchas pruebas manuales: ejecutábamos algunos despliegues comunes, observábamos dónde las cosas se comportaban de manera distinta a lo esperado, ajustábamos el prompt y volvíamos a ejecutar los despliegues.
Luego evaluamos el impacto de estos cambios usando nuestro benchmark interno, Cursor Bench, comparando agentes con y sin sandbox activado. Pronto notamos un patrón de fallo común: el agente reintentaba una y otra vez el mismo comando de terminal sin cambiar los permisos.
Para solucionar esto, actualizamos la forma en que se muestran los resultados de la herramienta Shell, exponiendo explícitamente la restricción del sandbox responsable del fallo y, en ciertos casos, recomendando que el agente eleve los permisos. Después de lanzar estos recordatorios, los agentes se recuperaron de forma mucho más sólida de fallos relacionados con el sandbox y el rendimiento en las evaluaciones offline mejoró significativamente.
Sin embargo, las evaluaciones offline solo muestran una parte pequeña del panorama. Para obtener garantías adicionales de que el sandbox no degradaría la experiencia del usuario, desplegamos el sandbox gradualmente en producción. Los comentarios que recibimos tanto interna como externamente nos dieron la confianza para lanzar la función. Ahora vemos que un tercio de las solicitudes en las plataformas compatibles se ejecutan con el sandbox, y hemos incorporado a muchos clientes Enterprise como NVIDIA.
A medida que los agentes pasan de generar código a operar sistemas de producción, proporcionar límites de ejecución es fundamental. Nuestra implementación actual es un paso en esa dirección. De cara al futuro, nos entusiasman especialmente los agentes nativos de sandbox entrenados en las restricciones de su entorno. A estos agentes se les puede dar la libertad de escribir scripts y programas directamente, en lugar de estar limitados a la invocación de herramientas.
Si te interesa trabajar en problemas técnicos profundos relacionados con el futuro de la programación, escríbenos a hiring@cursor.com.