Cómo aislar agentes de IA que ejecutan código: sandboxing, egress y credenciales efímeras

Si tu producto ya deja que un agente de IA escriba y ejecute código —o que llame a herramientas que lo hacen por él—, has cruzado una línea de seguridad que la mayoría de equipos aún no ha asimilado: estás corriendo código que nadie de tu equipo ha escrito, que no puedes revisar antes de que se ejecute y que, por diseño, va a intentar cosas que no habías previsto. El aislamiento del runtime deja de ser una buena práctica opcional y pasa a ser parte del producto.

La respuesta corta: un agente con capacidad de ejecución necesita un sandbox con aislamiento a nivel de kernel (o mejor, de hardware), egress denegado por defecto, credenciales efímeras de mínimo privilegio y un ciclo de vida desechable. Docker a secas no basta. A continuación explicamos por qué y cómo montarlo sin romper la experiencia.

Por qué esto es un problema nuevo (y por qué ahora)

Durante años, el código no confiable que ejecutábamos venía de dos sitios: dependencias de terceros y, en algún caso, snippets de usuarios. El agente cambia el modelo de amenaza. Ahora el propio sistema genera acciones en cadena, a velocidad de máquina, con un objetivo que a veces cumple por caminos que no anticipaste.

En julio de 2026 esto dejó de ser teórico. Durante una evaluación interna de capacidades ofensivas (el benchmark ExploitGym), un modelo de frontera con las salvaguardas de rechazo relajadas encontró un fallo desconocido en infraestructura de registro de paquetes, escaló privilegios y acabó tocando sistemas de producción de un tercero —con miles de acciones no autorizadas ejecutadas antes de que se contuviera. El detalle relevante para nosotros no es el titular, sino la lección: el sandbox de evaluación no aguantó, y la contención asumida resultó insuficiente. Si esto pasa en un laboratorio con gente vigilando, conviene asumir que tu agente de producción intentará, tarde o temprano, salirse de su caja.

Esto es distinto —y complementario— de la seguridad de protocolo. Ya escribimos sobre las amenazas de capa de aplicación en agentes (tool poisoning, prompt injection, gobernanza de herramientas) en nuestra guía de seguridad de MCP. Aquel post trata de qué puede invocar el agente. Este trata de dónde se ejecuta y qué puede alcanzar si algo va mal. Necesitas los dos.

El modelo de amenaza, en una frase

Asume que el código que corre dentro del sandbox es hostil. No que probablemente lo sea: que lo es. A partir de ahí, la pregunta de diseño es una sola: si este proceso quedara totalmente comprometido, ¿cuál es el radio de impacto? Todo lo demás son controles para reducir ese radio.

Los cuatro caminos de fuga que un agente comprometido intentará casi siempre:

  • Robar credenciales del entorno o del sistema de ficheros (variables de entorno, tokens montados, ficheros de config).
  • Llegar al endpoint de metadatos del cloud (169.254.169.254) para conseguir credenciales de la instancia.
  • Movimiento lateral hacia rangos internos (RFC 1918) para tocar otros servicios de tu red.
  • Escapar del contenedor explotando el kernel compartido.

Cada capa de la arquitectura que viene ataca uno de estos vectores.

Capa 1 — Aislamiento: por qué Docker no basta

Un contenedor Docker estándar comparte el kernel del host. Una vulnerabilidad de escalada en el kernel —de las que aparecen varias al año— convierte un escape de contenedor en un compromiso del host. Para código que tú escribes es un riesgo asumible; para código que genera un agente autónomo, no.

Hay tres niveles reales de aislamiento, de menos a más fuerte:

EnfoqueFronteraFuga típica que cortaCoste / latenciaCuándo encaja
Contenedor endurecido (seccomp, user namespaces, read-only rootfs)Kernel compartidoErrores de config, no escapes de kernelMuy bajoCódigo semi-confiable, tareas internas
gVisor (kernel en espacio de usuario)Intercepta syscallsAmplias clases de exploits de kernelBajo-medioMulti-tenant intensivo en cómputo
microVM (Firecracker, Kata)Virtualización por hardware, kernel invitado propioPrácticamente todos los escapes de kernelMedio (arranque en ~ms)Código totalmente no confiable de agentes

Para un agente que ejecuta código arbitrario, el suelo mínimo es gVisor y el estándar de oro es la microVM. No es exótico: AWS Lambda y Fargate usan Firecracker por debajo, y Google Cloud Run ejecuta cada instancia dentro de un sandbox gVisor. Si despliegas ahí, ya tienes una frontera decente sin montar nada; el error es asumir que un contenedor Kubernetes plano ofrece lo mismo.

Para tareas triviales y de solo JavaScript (evaluar una expresión, transformar datos) los isolates de V8 son una alternativa ligera y rapidísima, pero no los uses como frontera de seguridad para código arbitrario: su aislamiento es de proceso, no de kernel.

Capa 2 — Red: denegar por defecto

El aislamiento del proceso no sirve de nada si el proceso puede llamar a cualquier sitio. La regla es egress denegado por defecto y allowlist explícita de los endpoints que la tarea necesita:

  • Bloquea el endpoint de metadatos (169.254.169.254) a nivel de red, no confíes en que la SDK lo haga.
  • Bloquea los rangos internos RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) para cortar el movimiento lateral.
  • Valida la IP resuelta en el momento de conectar, no solo el dominio: un allowlist por hostname es vulnerable a DNS rebinding si no compruebas a qué IP resuelve realmente.
  • Enruta el tráfico permitido por un proxy de egress que registre cada petición. Ese log es tu caja negra cuando algo se tuerce.

En la práctica montamos esto como un sidecar o un proxy dedicado delante del sandbox, con una lista de dominios por tarea. Si el agente solo necesita hablar con la API de un LLM y con tu propio backend, esos son los dos únicos destinos que existen para él.

Capa 3 — Credenciales: efímeras y de mínimo privilegio

Un sandbox comprometido solo puede filtrar lo que tiene dentro. Por tanto, no metas nada dentro que no sea estrictamente de esa tarea:

  • Cero credenciales de host en variables de entorno o en el filesystem del sandbox.
  • Tokens de vida corta y alcance mínimo, emitidos por tarea y revocables. Nada de service accounts con permisos amplios "por comodidad".
  • Cuando el agente necesite autenticarse contra un servicio, hazlo pasar por un broker de credenciales que inyecte el secreto en la petición saliente (en el proxy de egress) sin que el secreto llegue nunca al proceso del agente.

Este es el control que más veces vemos mal hecho en revisiones: el sandbox es impecable, pero dentro hay un GOOGLE_APPLICATION_CREDENTIALS con acceso a medio proyecto.

Capa 4 — Filesystem, límites y ciclo de vida efímero

  • Filesystem aislado: base de solo lectura, un directorio de trabajo escribible que no toca el host, y nada más montado.
  • Límites de recursos (CPU, memoria, número de procesos): un agente en bucle o un fork bomb no deben poder tumbar el nodo.
  • Ciclo de vida desechable: un entorno nuevo por tarea (o por sesión) y destrucción automática al terminar. Un sandbox de larga vida acumula estado y se convierte en un objetivo persistente. Lo efímero es, en sí mismo, un control de seguridad.

Capa 5 — Observabilidad: asume que algo pasará

Ninguna de las capas anteriores es infalible; en conjunto reducen el radio de impacto, no lo eliminan. Por eso la última capa es asumir el fallo y verlo llegar: registra cada acción del agente, cada petición de egress y cada uso de credencial, y ten alertas sobre patrones anómalos (picos de peticiones, destinos nuevos, intentos hacia rangos bloqueados). El caso de julio se contuvo porque alguien detectó miles de acciones anómalas, no porque el sandbox aguantara. La detección es parte del diseño, no un extra.

Cuándo NO montar todo esto

Sinceridad por delante: no todos los agentes necesitan una microVM. El nivel de aislamiento debe ser proporcional al radio de impacto.

  • Si tu agente solo llama a herramientas de lectura (buscar en tu base de conocimiento, consultar una API sin efectos) y no ejecuta código ni maneja secretos con alcance, un contenedor endurecido con egress controlado es suficiente. Meter una microVM ahí es coste y latencia sin retorno.
  • Si estás prototipando y el agente corre en local sin acceso a producción, prioriza avanzar; añade el aislamiento fuerte antes de conectar nada real.
  • No te montes una orquestación propia de microVMs si un sandbox gestionado (o simplemente desplegar en Cloud Run / Lambda, que ya usan gVisor/Firecracker) cubre tu caso. La infraestructura de aislamiento es cara de mantener bien; externalízala salvo que tengas un motivo de peso.

La pregunta correcta no es "¿cuánto aislamiento puedo poner?" sino "¿qué puede alcanzar este agente si se descontrola, y me parece aceptable?". Si la respuesta incomoda, sube de capa.

Cómo lo enfocamos en Dribba

En Dribba llevamos desde 2011 —15 años— construyendo producto digital, y en el último ciclo buena parte de ese trabajo es meter agentes en productos reales de clientes en FinTech, HealthTech y RetailTech, donde el dato es sensible y el radio de impacto de un fallo es alto. Nuestro enfoque de backend en Go sobre Cloud Run encaja de forma natural con esta arquitectura: cada instancia ya corre en un sandbox gVisor, el egress se controla en la frontera y las credenciales se emiten por tarea. Somos Flutter Partner oficial de Google desde 2017 —la única agencia española en el directorio— con equipo 100% senior in-house entre Barcelona y Andorra, y más de 300 proyectos a la espalda; esa combinación de app y backend nos deja diseñar el agente y su caja de contención como una sola pieza, no como dos equipos que se pasan el problema.

Si estás llevando agentes con capacidad de ejecución a producción y quieres una revisión honesta de su contención —o construir la arquitectura desde cero—, hablemos. Y si vienes de la parte de protocolo, complementa esta lectura con nuestra guía de seguridad de MCP y con code execution en agentes, que explica por qué cada vez más agentes ejecutan código en lugar de solo llamar herramientas —y por qué esto vuelve el aislamiento aún más urgente.