Ejecuta Python, JavaScript y Bash no confiables en una jaula reforzada con límites de 5 segundos, 128 MB, 0.5 núcleos, PID y salida.
Ejecución de código no confiable aplicada por el kernel — cada carga útil confinada mediante cgroups v2, namespaces, seccomp-BPF y un rootfs de solo lectura, y cada ejecución auditada en PostgreSQL.
python · javascript · bash → jaula de 5 segundos, 128 MB, 0.5 núcleos, 32 PID, 512 KB de salida
Un servicio de ejecución reforzado en seguridad para código en el que no confías. Los llamadores envían el código fuente a través de una pequeña API REST; el daemon lanza cada carga útil dentro de una jaula efímera del kernel donde el propio kernel de Linux —no la lógica de la aplicación— garantiza la contención:
pivot_root sobre un rootfs de solo lectura),lo desactivado + seccomp elimina socket),PID · MOUNT · NET · IPC · UTS · USER), una estricta lista de permitidos seccomp-BPF, jaulas de recursos cgroups v2 y un sistema de archivos pivot_root de solo lectura con un espacio de trabajo tmpfs de 16 MB.5 s de tiempo real, techo de memoria de 128 MB (swap deshabilitado, eliminación instantánea por OOM), 0.5 núcleos de CPU, inmunidad a bombas de bifurcación con pids.max = 32, y límites de salida de 512 KB en stdout/stderr.execution_runs).flowchart LR
CLI["👤 API Client<br/><i>tenant / CI job</i>"]
subgraph CP["🔐 Trusted Control Plane — Go daemon"]
API["Ingestion Daemon<br/><i>net/http :8080</i>"]
POOL["Warm Runner Pool<br/><i>16 slots · 3 s cap</i>"]
RUN["Process Runner<br/><i>watchdog + pipes</i>"]
ISO["Kernel Isolation<br/><i>cgroups v2 · namespaces · seccomp-BPF</i>"]
end
subgraph JAIL["⛓️ Ephemeral Kernel Jail — untrusted"]
INIT["sandbox_init<br/><i>exec trampoline</i>"]
GUEST["💀 Untrusted Code<br/><i>python · node · bash</i>"]
end
PG[("🗄️ PostgreSQL 16<br/><i>execution_runs</i>")]
RD[("📮 Redis 7 Queue<br/><i>sandbox:jobs</i>")]
CLI -->|"POST /api/v1/execute"| API
API -->|"validate + acquire"| POOL
POOL -->|"spawn + limits"| RUN
RUN -.->|"apply jail"| ISO
ISO ==>|"seccomp · pivot_root"| GUEST
RUN -->|"fork / exec"| INIT
INIT -->|"syscall.Exec"| GUEST
RUN -.->|"stdout / stderr ≤ 512 KB"| POOL
API -.->|"async audit INSERT"| PG
RD -.->|"BRPop drain · worker module"| POOL
style JAIL fill:#2a1215,stroke:#f87171,stroke-width:2px
style CP fill:#0d1b2a,stroke:#38bdf8,stroke-width:1px
| Componente | Responsabilidad | Origen |
|---|---|---|
| Daemon de ingesta | Superficie REST: POST /api/v1/execute + /health; validación de solicitudes; emisión asíncrona de auditoría | cmd/server/main.go |
| Pool de runners precalentados | Slots de ejecución acotados por semáforo (16) con un tiempo de adquisición de 3 s → contrapresión por agotamiento al estilo 503 | internal/runner/pool.go |
| Runner de procesos | Construye el comando del lenguaje, adjunta el cgroup, transmite las tuberías mediante escritores truncadores, aplica el watchdog de 5 s, recopila métricas del cgroup, clasifica los resultados | internal/runner/process.go |
| Aislamiento del kernel | Limitador de cgroups v2 (memory.max, cpu.max, pids.max), flags de namespaces (CLONE_NEWPID/NET/NS/IPC/UTS/USER), compilador de filtros seccomp-BPF | internal/isolation/ |
| sandbox_init | Trampolín hijo: pivot_root de solo lectura + tmpfs /dev//tmp, desconexión de red (lo down), aplicación de seccomp y luego syscall.Exec del objetivo | cmd/sandbox_init/main.go |
| Código no confiable | La carga útil invitada. Dispositivos del host eliminados, /proc oculto (hidepid=2), todas las syscalls no incluidas en la lista de permitidos eliminadas | imágenes rootfs en runtimes/ |
| PostgreSQL 16 | Registro de auditoría duradero de cada ejecución, incluidas las violaciones de seguridad | migrations/001_init_sandbox_schema.sql |
| Redis 7 | Cola sandbox:jobs + worker BRPop que drena hacia el pool (módulo implementado, aún no conectado al daemon — véase Limitaciones conocidas) | internal/queue/redis_consumer.go |
| Límite | Qué separa | Aplicación |
|---|---|---|
| Cliente ↔ Daemon | Envío de cargas útiles no autenticadas desde el plano de control | validación de esquema (tenant_id, language, code) |
| Plano de control ↔ Jaula | Código Go confiable frente a carga útil hostil | fork hacia namespaces privados; pivot_root; seccomp con herencia en exec |
| Jaula ↔ Límites del kernel | Consumo de recursos del invitado frente a la capacidad del host | cgroups v2 memory.max=128MB, swap.max=0, cpu.max="50000 100000", pids.max=32 |
| Jaula ↔ Red | Cualquier salida o alcanzabilidad desde el lado del host | namespace NET privado, lo down, syscall socket eliminada |
🔍 Una versión interactiva y adaptable al tema de este diagrama (con exportación a PNG/SVG) se genera a partir de los candidatos respaldados por evidencia en
docs/archify/.
sequenceDiagram
autonumber
participant C as Client
participant A as REST API
participant P as Warm Pool
participant R as Process Runner
participant I as sandbox_init
participant G as Untrusted Code
participant DB as PostgreSQL