Summary
The current sidecar architecture runs the FastAPI server and the Python subprocess in the same container. This means they share a seccomp profile, PID namespace, and process memory. We can't block socket syscalls for the subprocess without also blocking them for uvicorn.
A separate-pod architecture would give the sandbox its own pod with its own seccomp profile, PID namespace, and network namespace — achieving the isolation benefits that OpenShell gets from running k3s, but without requiring SYS_ADMIN or root.
Motivation
- Seccomp per-process: The sandbox subprocess doesn't need
socket, bind, connect, etc. A separate pod could have a seccomp profile that blocks all networking syscalls, closing the UDP gap that Landlock v4 doesn't cover.
- PID namespace isolation: The subprocess currently can signal PID 1 (the server). A separate pod would have its own PID namespace.
- Memory isolation: The subprocess shares process memory with the server. A separate pod eliminates this.
- Restricted-v2 compatible: Unlike OpenShell's k3s approach (requires SYS_ADMIN + root), separate pods work under OpenShift's restricted-v2 SCC.
Tradeoffs
|
Sidecar (current) |
Separate Pod |
| Latency |
localhost (sub-ms) |
Service network (~1ms) |
| Seccomp |
Shared with server |
Independent |
| PID namespace |
Shared |
Isolated |
| Deployment |
Single pod |
Two pods + Service |
| Scaling |
Coupled |
Independent |
| Complexity |
Lower |
Higher (network, health checks) |
Design Sketch
- Sandbox runs as a Deployment + Service in the same namespace
- Agent's
code_executor tool points at the Service URL instead of localhost
SANDBOX_URL env var already supports this (defaults to http://localhost:8000)
- The Helm chart would deploy both the agent and sandbox as separate Deployments
- Sandbox pod gets its own SeccompProfile CRD that blocks all networking syscalls
- Two-layer Landlock still applies inside the sandbox pod
Context
This came out of observing that OpenShell runs k3s inside the container specifically to get a real pod boundary between server and execution. Our sidecar approach works with Landlock stacking but hits limits with seccomp sharing. A separate pod is the restricted-v2-compatible way to get the same isolation.
Related
- Current sidecar implementation:
chart/values.yaml sandbox section
- Seccomp stacking investigation: NEXT_SESSION.md Priority 3a
- OpenShell architecture: docs/sandbox-hardening-v2.md Finding 4
Summary
The current sidecar architecture runs the FastAPI server and the Python subprocess in the same container. This means they share a seccomp profile, PID namespace, and process memory. We can't block
socketsyscalls for the subprocess without also blocking them for uvicorn.A separate-pod architecture would give the sandbox its own pod with its own seccomp profile, PID namespace, and network namespace — achieving the isolation benefits that OpenShell gets from running k3s, but without requiring
SYS_ADMINor root.Motivation
socket,bind,connect, etc. A separate pod could have a seccomp profile that blocks all networking syscalls, closing the UDP gap that Landlock v4 doesn't cover.Tradeoffs
Design Sketch
code_executortool points at the Service URL instead of localhostSANDBOX_URLenv var already supports this (defaults tohttp://localhost:8000)Context
This came out of observing that OpenShell runs k3s inside the container specifically to get a real pod boundary between server and execution. Our sidecar approach works with Landlock stacking but hits limits with seccomp sharing. A separate pod is the restricted-v2-compatible way to get the same isolation.
Related
chart/values.yamlsandbox section