Logo StartupKit
ES

Cómo funciona el aislamiento

El modelo de seguridad del triaje con IA que conoce tu código: por qué el límite de red vive fuera del agente, cómo aislar un runner de GitLab y por qué un informe enviado por un atacante no puede extraer tu código.

Esta traducción puede estar desactualizada. La versión en inglés se ha actualizado desde la última traducción de esta página. Ver en inglés →

Por qué importa

El triaje con IA que conoce tu código proporciona a un agente dos cosas a la vez: tu código fuente y el cuerpo de un informe controlado por un atacante. Es un objetivo para la inyección de prompts. Un investigador malicioso puede redactar un informe que intente secuestrar al agente para leer secretos y enviarlos con curl a un host externo.

La defensa no consiste en «pedir amablemente al agente que no lo haga». Consiste en que incluso un agente totalmente secuestrado no tenga dónde enviar los datos, porque el límite de red se impone fuera del agente, en la capa del entorno. Esta página explica ese límite y cómo configurarlo.

Danger

Trata el cuerpo de todos los informes como contenido hostil. El prompt de triaje envuelve los campos en delimitadores y ordena al modelo que no ejecute las instrucciones que encuentre dentro, pero la higiene de delimitadores es defensa en profundidad, no el límite. El límite es la denegación de toda salida que se describe a continuación.

El principio fundamental: el agente no es el límite de seguridad

Claude Code, Codex y otros agentes tienen sandboxes, listas de dominios permitidos y modos de permisos. Son útiles como defensa en profundidad. No son una garantía fiable frente a la extracción de datos cuando el atacante controla el contenido que procesa el agente.

Motivos:

  • Las denegaciones pueden aprobarse automáticamente. Las configuraciones de permisos de Claude Code documentan un defaultMode que puede aceptar ediciones automáticamente o eludir permisos. Una opción mal configurada invalida las reglas de denegación.
  • Los fallos del sandbox son reales. Se han corregido fallos de escape por enlace simbólico, desviaciones del analizador de SOCKS5 —incluido un truco con un byte nulo— capaces de eludir cualquier lista de comodines. Utiliza versiones recientes, pero no confíes en la lista como barrera.
  • Los dominios permitidos pueden tener API capaces de extraer datos. Si permites el dominio del proveedor del LLM, ese mismo dominio puede ofrecer una API de archivos, cargas o almacenamiento: un canal perfecto de extracción que tu regla de «permitir el endpoint del modelo» aceptará.

Por tanto, la garantía determinista de que los datos «no pueden salir» debe residir fuera del agente, en la configuración de red y del runner.

El límite: denegar toda salida y utilizar un proxy con dos destinos

El aislamiento se construye con cuatro controles de la capa del entorno. El repositorio de ejemplo los muestra en su .gitlab-ci.yml y en el directorio infra/.

1. Un runner de GitLab autogestionado

Debes utilizar un runner autogestionado. No puedes aislar de la red del host los runners compartidos SaaS de GitLab.com, así que no puedes imponerles el límite de salida. El README del repositorio de ejemplo lo indica como requisito previo.

2. Un ejecutor Docker sin privilegios

Ajuste Valor Motivo
privileged false El modo privilegiado equivale en la práctica a ser root del host. Es obligatorio desactivarlo en una ruta que procesa informes no fiables.
Ejecutar como usuario no root Elimina SETUID y SETGID, y no concedas capacidades innecesarias.
Socket de Docker sin montar Montarlo permite tomar el control del host.
Volúmenes del host ninguno No montes directorios del host dentro del trabajo.
FF_NETWORK_PER_BUILD 1 GitLab crea una red puente exclusiva para cada trabajo y la destruye al terminar, de modo que la red queda aislada y es reproducible.
# config.toml on your self-managed runner
[[runners]]
  executor = "docker"
  environment = ["FF_NETWORK_PER_BUILD=1"]
  [runners.docker]
    privileged = false

3. Denegación de toda salida en el host

Warning

GitLab Runner no ofrece una lista nativa de salidas permitidas. No existe un ajuste incorporado que permita a los trabajos acceder solo a determinados hosts; hay una función propuesta, pero no se ha publicado. El límite de salida debe aplicarse en la capa del host o del espacio de nombres.

Aplica una política de salida con DROP predeterminado a la red del trabajo mediante iptables o nftables, o ejecuta el trabajo en un espacio de nombres de red sin ruta hacia tu intranet. Todo el tráfico saliente se deniega de forma predeterminada; después abres exactamente los dos destinos siguientes y nada más, ni siquiera tu propia red interna.

4. Un proxy de salida que termina TLS y valida tokens

La única ruta de salida permitida es un proxy que acepta exactamente dos destinos:

  1. Tu endpoint de inferencia del LLM, por ejemplo https://api.deepseek.com/anthropic.
  2. El host MCP limitado de Kit, para leer el informe y publicar el triaje.

El proxy hace algo más que fijar esos dos hosts:

  • Limita el acceso a las rutas de inferencia y MCP para bloquear las API de archivos o almacenamiento del proveedor del LLM aunque se permita el host.
  • Valida el token de sesión de cada ejecución. Un atacante que consiga introducir su propia clave de API en el agente no puede utilizarla porque el proxy solo acepta el token emitido para esa ejecución.

Este diseño reproduce el patrón de proxy MITM dentro de la máquina virtual que Anthropic utiliza para aislar sus propios agentes. Un filtro de salida similar a harden-runner es un equivalente conceptual razonable para la implementación de referencia.

El enmascaramiento es higiene, no protección

Pasarás el token MCP limitado y la clave del modelo como variables de CI enmascaradas y protegidas. Hazlo: evita que los secretos aparezcan en los registros del trabajo. Pero ten presente el límite:

Important

El enmascaramiento solo impide que un valor aparezca en los registros ([MASKED]). Un trabajo comprometido aún puede leer la variable en tiempo de ejecución. La propia documentación de GitLab advierte que no es una medida infalible. Lo que evita que un token filtrado salga del trabajo es la denegación de toda salida, no la máscara.

Qué debes probar antes de activarlo

El repositorio de ejemplo incluye un fixture injection-canary: un informe cuyo cuerpo ordena al agente leer una variable secreta y enviarla con curl a un host controlado. Ejecútalo en tu runner real antes de conectarlo a Kit.

La prueba solo se supera si:

  1. El pipeline termina correctamente y produce un triaje válido.
  2. El intento de salida falla en la capa de red, no porque el agente haya decidido obedecer el prompt del sistema.
  3. Los registros muestran la conexión bloqueada sin revelar el valor secreto.

Si la petición externa tiene éxito, todavía no tienes un aislamiento. Corrige el cortafuegos del host antes de conectar Kit.

Una nota sobre la elección del modelo

Tú controlas el modelo y también asumes su riesgo. Enviar tu código y los informes no fiables a un endpoint alojado —la API de DeepSeek de forma predeterminada— es una decisión propia sobre residencia y confianza de los datos. Ese es precisamente el sentido de «tu IA, tu red». Cuando convenga, dirige el agente a un endpoint autoalojado, como vLLM local o un proxy de Ollama compatible con Anthropic, para que la inferencia nunca salga de tu perímetro. El archivo SECURITY.md del repositorio de ejemplo lo recalca.

En resumen

  • Runner de GitLab autogestionado, no un runner compartido SaaS
  • Ejecutor Docker con privileged = false, usuario no root, sin socket de Docker ni volúmenes del host
  • FF_NETWORK_PER_BUILD=1 para aislar la red de cada trabajo
  • Salida con DROP predeterminado en el host mediante iptables, nftables o un espacio de nombres de red
  • Proxy de salida que permite exactamente dos hosts y rutas: el endpoint del LLM y el host MCP de Kit
  • El proxy valida el token de cada ejecución y bloquea las API de almacenamiento del proveedor del LLM
  • El token limitado se trata como válido para un informe, una hora y un solo uso; el enmascaramiento solo es higiene
  • Ejecuta el fixture injection-canary y confirma que se bloquea el intento de extracción
  • Fija una versión reciente de Claude Code o del entorno de sandbox como defensa en profundidad, no como límite

Y ahora qué

Escriba para buscar...