
Executes untrusted Python, JavaScript, and Bash in a hardened jail with 5-second, 128 MB, 0.5-core, PID and output limits.
Kernel-enforced execution of untrusted code — every payload jailed by cgroups v2, namespaces, seccomp-BPF and a read-only rootfs, and every run audited in PostgreSQL.
python · javascript · bash → 5-second, 128 MB, 0.5-core, 32-PID, 512 KB-output jail
A security-hardened execution service for code you do not trust. Callers submit source over a small REST API; the daemon spawns each payload into an ephemeral kernel jail where the Linux kernel itself — not application logic — guarantees containment:
pivot_root onto a read-only rootfs),lo down + seccomp kills socket),PID · MOUNT · NET · IPC · UTS · USER), a strict seccomp-BPF allowlist, cgroups v2 resource jails, and a read-only pivot_root filesystem with a 16 MB tmpfs scratch space.5 s wall-clock timeout, 128 MB memory ceiling (swap disabled, instant OOM kill), 0.5 CPU core, pids.max = 32 fork-bomb immunity, and 512 KB output caps on 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
| Component | Responsibility | Source |
|---|---|---|
| Ingestion Daemon | REST surface: POST /api/v1/execute + /health; request validation; async audit emission | cmd/server/main.go |
| Warm Runner Pool | Semaphore-bounded execution slots (16) with a 3 s acquire timeout → 503-style exhaustion backpressure | internal/runner/pool.go |
| Process Runner | Builds the language command, attaches the cgroup, streams pipes through truncating writers, enforces the 5 s watchdog, harvests cgroup metrics, classifies results | internal/runner/process.go |
| Kernel Isolation | cgroups v2 limiter (memory.max, cpu.max, pids.max), namespace flags (CLONE_NEWPID/NET/NS/IPC/UTS/USER), seccomp-BPF filter compiler | internal/isolation/ |
| sandbox_init | Child trampoline: read-only pivot_root + tmpfs /dev//tmp, network detachment (lo down), seccomp apply, then syscall.Exec of the target | cmd/sandbox_init/main.go |
| Untrusted Code | The guest payload. Host devices stripped, /proc hidden (hidepid=2), all non-allowlisted syscalls killed | runtimes/ rootfs images |
| PostgreSQL 16 | Durable audit log of every run, including security violations | migrations/001_init_sandbox_schema.sql |
| Redis 7 | sandbox:jobs queue + BRPop worker draining into the pool (module implemented, not yet wired into the daemon — see Known Limitations) | internal/queue/redis_consumer.go |
| Boundary | What it separates | Enforcement |
|---|---|---|
| Client ↔ Daemon | Unauthenticated payload submission from control plane | schema validation (tenant_id, language, code) |
| Control plane ↔ Jail | Trusted Go code vs. hostile payload | fork into private namespaces; pivot_root; seccomp inherit-on-exec |
| Jail ↔ Kernel limits | Guest resource consumption vs. host capacity | cgroups v2 memory.max=128MB, swap.max=0, cpu.max="50000 100000", pids.max=32 |
| Jail ↔ Network | Any egress or host-side reachability | private NET namespace, lo down, socket syscall killed |
🔍 An interactive, theme-aware version of this diagram (with PNG/SVG export) is authored from the evidence-backed candidates in
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
C->>A: POST /api/v1/execute
A->>P: acquire slot · 16 max, 3 s timeout
P->>R: Run(req, limits)
R->>I: fork under CLONE_NEWPID·NET·NS·IPC·UTS·USER
R->>R: create cgroup scope → attach PID<br/>128 MB · 0.5 CPU · 32 PIDs
I->>I: pivot_root RO rootfs · lo down · seccomp-BPF
I->>G: syscall.Exec target interpreter
G-->>R: stdout / stderr via pipes (512 KB cap)
R->>R: watchdog: SIGKILL at 5 s → exit 137
R-->>P: result + cgroup metrics (peak mem, CPU)
P-->>A: ExecutionResult
A-->>C: 200 JSON
A-)DB: async audit INSERT (non-blocking)
Step-by-step: