devto 2026-09-05 원문 보기 ↗
This is a companion map to my Building ShrekOS series. If you have read Part 2, you have the argument already. This post is the picture: how an untrusted workload gets to do real work while reaching almost nothing.
The whole thing runs on one idea. An agent, or any untrusted job, runs inside a Bench: a disposable box that starts with no files and no network, and is handed capabilities one at a time, narrowly, and revocably.
noexec. A swapped symlink cannot redirect it, and files cannot be directly executed from the granted host mount.flowchart TB
BN["Bench (default: no net)"] --> P{"sealed profile (pinned)"}
P -->|apt| DEB["deb.debian.org"]
P -->|pip| PY["PyPI"]
P -->|model| BR["broker to provider"]
BN -.->|blocked| H["host-local"]
sequenceDiagram
autonumber
actor U as You / Agent
participant GK as gatekeeperd
participant BN as Bench
participant NET as Outside
U->>GK: create
U->>GK: grant [in]/[out] (pinned, noexec)
U->>GK: run
GK->>BN: start, NO network (holder PID 1)
Note over BN,NET: fail-closed: zero egress
GK->>BN: inject veth + nft allowlist
BN->>NET: deb.debian.org:443 only
U->>GK: destroy (output kept, tooling gone)
The last line is the point of the whole design. The box is thrown away, but the file it produced stays. Disposability protects the host's future; it does nothing about the present blast radius, which is why the grants above matter more than the teardown.
The mechanics behind each rule get their own parts in the series: why a Bench at all (Part 2), how a single grant is made attacker-proof, and how the one egress door stays honest. This post is just the map to hang them on.