Skip to main content
Glama

agent-sandbox

Lo construí para permitir que un agente de codificación de IA ejecute comandos reales de infraestructura contra un clúster real de Kubernetes, sin tener nunca una credencial permanente y sin poder destruir nada sin supervisión.

Tres herramientas MCP. Cada llamada se ejecuta dentro de un Job de Kubernetes con sandbox de gVisor, con una credencial de corta duración y alcance limitado que Vault emite para esa única acción. Cualquier cosa destructiva se detiene en una puerta de aprobación humana.

AI Agent (Claude Desktop / Cursor)
        │  MCP protocol (stdio)
        ▼
┌──────────────────────────────────────────┐
│  MCP Server            src/agent_sandbox │
│    3 tools -> guardrails -> broker ->    │
│    sandbox -> audit                      │
└───────┬──────────────────────┬───────────┘
        │                      │
        ▼                      ▼
┌────────────────┐   ┌──────────────────────────┐
│ Credential     │   │ Sandbox Runner           │
│ Broker (Vault) │   │ K8s Job + gVisor         │
│ 10-min leases  │   │ restricted PSS           │
│ per-action     │   │ default-deny NetworkPolicy│
│ scope          │   │ cpu/mem limits, deadline │
└────────────────┘   └──────────────────────────┘
        │                      │
        └──────────┬───────────┘
                   ▼
        ┌──────────────────────┐
        │ Guardrails + Approval│
        │ policy.yaml, SQLite, │
        │ agent-sandbox CLI    │
        └──────────────────────┘

Por qué lo construí

Una herramienta de IA que estaba usando propuso una vez un cambio de Terraform contra infraestructura de producción que habría forzado el reemplazo de un recurso en vivo. El plan parecía rutinario. El modo de fallo no era que el modelo estuviera equivocado, sino que nada se interponía entre un plan de apariencia plausible y un apply destructivo.

Construí este proyecto como la capa que faltaba, en código funcional:

  • el agente nunca tiene una credencial que pueda reutilizar

  • todo se ejecuta en un lugar donde no puede dañar el host

  • los cambios destructivos se detienen y esperan a una persona

  • cada acción queda registrada

make demo reproduce el escenario exacto con el que me encontré. Una edición de etiqueta de una línea fuerza el reemplazo de un Deployment en ejecución, y la puerta lo detecta.

Related MCP server: Emisar

Inicio rápido

Requiere Docker, kind, kubectl, vault, terraform y Python 3.11+.

brew install kind kubectl hashicorp/tap/vault terraform
make up      # ~5 minutes from cold: cluster, CNI, gVisor, Vault, image, verify
make demo    # the forces-replacement guardrail demo
make down    # tear it all down

make up es idempotente. Termina ejecutando make verify, que prueba las afirmaciones de aislamiento en lugar de asumirlas (ver más abajo).

Apuntar un agente hacia él

cp examples/claude_desktop_config.json \
   ~/Library/Application\ Support/Claude/claude_desktop_config.json

Cursor: copia examples/cursor_mcp.json en .cursor/mcp.json. Luego pide al agente que "compruebe el estado de los pods en demo-app" o que "planifique el terraform de k8s-demo".

Las tres herramientas

Herramienta

Riesgo

Comportamiento

k8s_get_pod_status(namespace)

bajo

Se ejecuta inmediatamente. Credencial limitada a get/list/watch pods en un solo namespace.

terraform_plan(working_dir)

bajo

Se ejecuta inmediatamente. Guarda el plan para que un apply posterior ejecute exactamente el diff revisado.

terraform_apply(working_dir, approval_id?)

alto

Sin approval_id: calcula el plan, registra una aprobación pendiente, no aplica nada. Con uno: consume la aprobación y aplica el plan guardado.

Los cuatro componentes

1. Ejecución con sandbox — src/agent_sandbox/sandbox.py

Un Job desechable por llamada de herramienta. Cada control está ahí por una razón específica:

Control

Previene

runtimeClassName: gvisor

Las syscalls llegan al centinela de gVisor, no al kernel del host

PSS restricted, aplicado por el servidor de API

root, escalada de privilegios, capabilities, rootfs escribible

automountServiceAccountToken: false

Cualquier identidad de clúster ambiental dentro del sandbox

NetworkPolicy de denegación por defecto + lista blanca del servidor de API

Salida a Internet, movimiento lateral, endpoints de metadatos

resources.limits, activeDeadlineSeconds

Un Job descontrolado que agota el nodo o se cuelga para siempre

backoffLimit: 0

Una acción destructiva fallida que se reintenta silenciosamente

La credencial se monta como archivo, nunca como variable de entorno — las variables de entorno se filtran a través de kubectl describe, /proc y volcados de memoria.

2. Broker de credenciales — src/agent_sandbox/broker.py

cred = broker.issue_scoped_credential("k8s_get_pod_status")
# -> Vault mints a ServiceAccount + Role + RoleBinding, 10-minute lease
# -> revoked immediately after the Job finishes
  • El agente nunca elige su propio alcance. El alcance se deriva de la acción.

  • Denegación por defecto. Una acción sin alcance mapeado no obtiene credencial.

  • El radio de explosión está controlado. Se rechaza solicitar cualquier namespace que no sea el objetivo.

  • El token nunca sale del módulo. Credential.__repr__ imprime token=<redacted>, de modo que incluso un registro accidental no puede filtrarlo.

Lo verifiqué manualmente: un token pod-reader lista pods en demo-app, se le deniega en kube-system, se le deniega en secrets, y deja de funcionar en el momento en que se revoca su lease — sin dejar ningún ServiceAccount detrás.

3. Salvaguardas — policy/policy.yaml, src/agent_sandbox/guardrails.py

Denegación por defecto: registrar una herramienta MCP no es suficiente para que sea invocable. Una herramienta ausente de la política es rechazada, por lo que agregar capacidad requiere una decisión deliberada de nivel de riesgo.

Las aprobaciones están endurecidas contra los ataques obvios:

  • de un solo uso — se consumen dentro de una transacción SQLite, por lo que dos applies concurrentes no pueden gastar la misma aprobación

  • vinculadas a parámetros — vinculadas a un hash de la herramienta exacta + parámetros, por lo que una aprobación para k8s-demo no puede reproducirse contra prod-cluster

  • con expiración — 30 minutos por defecto

  • fuera de banda — se otorgan mediante un proceso CLI separado. No hay herramienta MCP para aprobar nada; el agente no tiene ruta de código para aprobar su propia solicitud.

4. Servidor MCP — src/agent_sandbox/server.py

Construido sobre el SDK oficial de Python (mcp 2.0, MCPServer). La capa de transporte es deliberadamente delgada y no otorga autoridad propia — un error allí no puede ampliar lo que el agente puede hacer, porque la política y la admisión de seguridad de Pods del servidor de API son los controles reales.

Registro de auditoría

Cada llamada emite un rastro de eventos correlacionado a var/audit.jsonl:

tool.request -> guardrail.decision -> credential.issued -> sandbox.started
   -> sandbox.completed -> credential.revoked -> tool.result
make audit
./.venv/bin/agent-sandbox audit --request-id req-4239b8bb5459 --json

Los valores de credenciales se eliminan recursivamente antes de escribir; se conservan el alcance, el ID de lease y el TTL. Una prueba afirma que ninguna cadena con forma de JWT llega al registro.

Verificado, no asumido

Dos cosas en este proyecto son fáciles de afirmar y no tenerlas realmente, así que no las di por sentadas. make verify prueba ambas contra el clúster en vivo:

== 1. gVisor kernel check ==
     kernel reported: Linux version 4.19.0-gvisor
  PASS: sandbox runs on the gVisor sentry kernel
== 2. NetworkPolicy egress enforcement check ==
  PASS: baseline connectivity works (got PONG)
  PASS: default-deny egress enforced (traffic blocked)

Esto detectó un problema real mientras lo construía. El CNI predeterminado de kind (kindnet) acepta objetos NetworkPolicy y los ignora silenciosamente — apliqué una política de denegación de salida por defecto y el tráfico pod-a-pod aún pasaba. El sandbox habría parecido bloqueado mientras tenía acceso completo a la red. Lo arreglé deshabilitando kindnet e instalando Calico, que aplica de verdad. Ver scripts/install-calico.sh.

También me encontré con una trampa relacionada al permitir el servidor de API: el ClusterIP no funciona, porque kube-proxy hace DNAT al endpoint real antes de que Calico evalúe la salida. El síntoma era un sandbox que simplemente se colgaba sin ningún evento de denegación de política que lo explicara. Documentado en scripts/apply-sandbox-policy.sh.

Limitaciones honestas

  • gVisor se ejecuta, pero esto sigue siendo kind. Instalé runsc dentro del nodo de kind (un contenedor en la VM Linux de Docker Desktop) y verifiqué que está activo. Eso es un sandbox real de gVisor, no un nodo endurecido para producción.

  • La ruta AWS/STS es condicional. scripts/vault-setup.sh solo configura el motor de secrets de AWS de Vault cuando hay credenciales reales de AWS presentes; sin ellas, se omite y lo dice. No quise falsificar esa ruta solo para que la demo pareciera completa. La ruta de credenciales en vivo y demostrable es la de Kubernetes, que es completamente real: ServiceAccounts dinámicos, RBAC real, leases reales, revocación real.

  • Vault se ejecuta en modo dev — en memoria, token root root, sin sellado. Está bien para un proyecto local, no algo que desplegaría tal cual.

  • La detección de señales destructivas es coincidencia de cadenas en la salida del plan. Es una ayuda de superficie para el humano, no un límite de seguridad — terraform_apply ya es de nivel alto y está controlado independientemente de lo que encuentre el escaneo.

  • Clúster de un solo nodo, por lo que el PVC que contiene el estado de Terraform es ReadWriteOnce en un nodo.

Estructura

cluster/      kind config, RuntimeClass, namespaces, RBAC, network policy
images/       sandbox runner image (terraform + kubectl, providers vendored)
policy/       guardrail policy: risk tiers and destructive signals
scripts/      up/down, gVisor + Calico install, verification, demo
src/          the package: broker, sandbox, guardrails, approvals, audit, MCP
terraform/    demo module managed by the agent
tests/        56 unit tests + a real-stdio MCP integration check

Pruebas

make test       # 56 unit tests, no cluster required
make test-mcp   # drives the server over real MCP stdio (needs the stack up)
make verify     # proves gVisor + NetworkPolicy enforcement on the live cluster
F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to securely perform privileged actions like creating GitHub issues by minting short-lived, single-purpose tokens on demand, with policy enforcement and audit logging.
    MIT
  • F
    license
    Not graded
    quality
    A
    maintenance
    Give AI agents Zero-Trust access to production infrastructure without the risks of granting them shell access. Actions are bounded by policy and an on-host runner.
    409
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI coding agents to evaluate actions against team-defined policies, record decisions, and obtain human approvals for potentially risky operations.
    165
    1
  • A
    license
    C
    quality
    B
    maintenance
    A policy-aware MCP server for GitHub and GitHub Actions that enables safe AI-assisted infrastructure workflows—inspecting repositories, preparing branches and pull requests, and constrained remote mutations behind explicit preview-bound approval tokens.
    18
    MIT

View all related MCP servers

Related MCP Connectors

  • Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.

  • Runtime permission, approval, and audit layer for AI agent tool execution.

  • The bridge from K2 agents through Wrangler to your master AI - safe, approval-gated Cloudflare ops.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mustafa12z/agent-mcp-sandbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server