
Führt nicht vertrauenswürdiges Python, JavaScript und Bash in einer gehärteten Jail-Umgebung mit 5-Sekunden-, 128-MB-, 0,5-Kern-, PID- und Ausgabelimits aus.
Kernel-erzwungene Ausführung von nicht vertrauenswürdigem Code — jede Payload wird durch cgroups v2, Namespaces, seccomp-BPF und ein schreibgeschütztes Rootfs eingesperrt, und jeder Lauf wird in PostgreSQL auditiert.
python · javascript · bash → 5-Sekunden-, 128-MB-, 0,5-Kern-, 32-PID-, 512-KB-Ausgabe-Jail
Ein sicherheitsgehärteter Ausführungsdienst für Code, dem Sie nicht vertrauen. Aufrufer übermitteln Quellcode über eine kleine REST-API; der Daemon startet jede Payload in einem ephemeren Kernel-Jail, in dem der Linux-Kernel selbst — nicht die Anwendungslogik — die Eindämmung garantiert:
pivot_root auf ein schreibgeschütztes Rootfs),lo down + seccomp beendet socket),PID · MOUNT · NET · IPC · UTS · USER), eine strikte seccomp-BPF-Allowlist, cgroups v2-Ressourcen-Jails und ein schreibgeschütztes pivot_root-Dateisystem mit einem 16-MB-tmpfs-Scratch-Bereich.5 s-Wall-Clock-Timeout, 128 MB-Speicherobergrenze (Swap deaktiviert, sofortiger OOM-Kill), 0,5 CPU-Kern, pids.max = 32 Fork-Bomben-Immunität und 512 KB-Ausgabeobergrenzen für stdout/stderr.execution_runs) geschrieben.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
| Komponente | Verantwortlichkeit | Quelle |
|---|---|---|
| Ingestion-Daemon | REST-Oberfläche: POST /api/v1/execute + /health; Anfragevalidierung; asynchrone Audit-Ausgabe | cmd/server/main.go |
| Warm Runner Pool | Semaphore-begrenzte Ausführungsslots (16) mit einem 3-s-Acquire-Timeout → 503-artige Erschöpfungs-Gegendruck | internal/runner/pool.go |
| Process Runner | Erstellt den Sprachbefehl, hängt die cgroup an, streamt Pipes durch kürzende Writer, erzwingt den 5-s-Watchdog, erfasst cgroup-Metriken, klassifiziert Ergebnisse | 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 | Kind-Trampolin: schreibgeschütztes pivot_root + tmpfs /dev//tmp, Netzwerk-Abtrennung (lo down), seccomp anwenden, dann syscall.Exec des Ziels | cmd/sandbox_init/main.go |
| Nicht vertrauenswürdiger Code | Die Gast-Nutzlast. Host-Geräte entfernt, /proc verborgen (hidepid=2), alle nicht auf der Allowlist stehenden Syscalls beendet | runtimes/ rootfs-Images |
| PostgreSQL 16 | Dauerhaftes Audit-Log jedes Laufs, einschließlich Sicherheitsverstößen | migrations/001_init_sandbox_schema.sql |
| Redis 7 | sandbox:jobs-Queue + BRPop-Worker, der in den Pool abfließt (Modul implementiert, noch nicht in den Daemon eingebunden — siehe Bekannte Einschränkungen) | internal/queue/redis_consumer.go |
| Grenze | Was sie trennt | Durchsetzung |
|---|---|---|
| Client ↔ Daemon | Nicht authentifizierte Payload-Übermittlung von der Steuerungsebene | Schema-Validierung (tenant_id, language, code) |
| Steuerungsebene ↔ Jail | Vertrauenswürdiger Go-Code vs. feindliche Payload | fork in private Namespaces; pivot_root; seccomp inherit-on-exec |
| Jail ↔ Kernel-Limits | Gast-Ressourcenverbrauch vs. Host-Kapazität | cgroups v2 memory.max=128MB, swap.max=0, cpu.max="50000 100000", pids.max=32 |
| Jail ↔ Netzwerk | Jeglicher Egress oder hostseitige Erreichbarkeit | privater NET-Namespace, lo down, socket-Syscall beendet |
🔍 Eine interaktive, theme-fähige Version dieses Diagramms (mit PNG/SVG-Export) wird aus den evidenzbasierten Kandidaten in
docs/archify/erstellt.
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)
Schritt für Schritt: