Sandbox runtimes
A sandbox’s RuntimeClass decides what stands between agent-directed code and the host kernel. This page answers what else it decides: which of the sandbox’s protections still hold under gVisor, under Kata, and under Kata on Firecracker. For how to set a RuntimeClass, see Run agents under gVisor or Kata. For the protections themselves, see Sandbox security.
What each runtime keeps
Section titled “What each runtime keeps”gVisor puts a user-space kernel between the workload and the host’s. Kata runs the pod in a lightweight VM with its own guest kernel, on a hypervisor such as QEMU, Cloud Hypervisor or Firecracker.
A runtime can change which of the sandbox’s other protections hold. Each
was measured: Omnia’s sandbox pod shape (the restricted security context, a
/workspace subPath of an NFS volume, a Secret volume, a bounded scratch
volume and the NetworkPolicy) was run under each runtime.
| Protection | runc | gVisor | Kata (QEMU, Cloud Hypervisor) | Kata on Firecracker |
|---|---|---|---|---|
| Ingress only from the owning agent | ✓ | ✓ | ✓ | ✓ |
| Egress denied except declared peers | ✓ | ✓ | ✓ | ✓ |
/workspace shows only the claim’s directory | ✓ | ✓ | ✓ | ✓ |
Writes to /workspace reach the volume | ✓ | ✓ | ✓ | ✗ |
Scratch sizeLimit enforced | ✓ | ✓ | ✓ | ✗ |
| Secret files readable, no ServiceAccount token | ✓ | ✓ | ✓ | ✓ |
| Seccomp filter on the workload | ✓ | gVisor’s own | none inside the VM | none inside the VM |
| Kernel the workload sees | host | gVisor | guest VM | guest VM |
Three results shape what you can rely on.
- Kata applies no seccomp filter inside its VM. The guest kernel is the boundary instead, and an exploit has to escape the VM to reach the host.
- Firecracker has no shared filesystem. The guest gets a copy of the
workspace volume: it reads correctly, but its writes stay inside the VM, and
a scratch volume’s
sizeLimitgoes unenforced. Firecracker suits only a class with neither a workspace nor scratch, and none of the shipped classes qualifies. - The kubelet follows a
subPathsymlink before any runtime sees the mount. A link from a claim’s directory to a sibling’s is followed on every runtime, gVisor and Kata included. Before it builds the pod, the operator refuses a mount whose directory, or any directory above it in the volume, is a symlink. That check is the guard whichever runtime you choose.
The NetworkPolicy holds under every runtime because it is enforced on the node, outside the pod.
Every Omnia release re-checks the table. Before a build is published, a conformance suite runs sandboxes through the operator on runc, gVisor, Kata with QEMU, Kata with Cloud Hypervisor, and Kata on Firecracker, and asserts each protection above. A runtime upgrade that drops one fails the release instead of reaching you.
Each class reports what its runtime gives it. The operator resolves the
RuntimeClass to a runtime family (runc, gvisor, kata,
kata-firecracker or unknown) and writes it, with the protections that hold
there, to the class’s status. A class whose RuntimeClass does not exist, or a
Firecracker class with a workspace or scratch volume, reports Ready=False, and its claims fail
rather than start. A RuntimeClass Omnia does not recognise is reported as
unknown and allowed: none of the protections above is verified on it. See
Class status.
The cost is speed. Every runtime measured started the sandbox pod within a few seconds, but gVisor intercepts every system call, so syscall-heavy and small-file work, such as builds, runs slower than on runc.
Related pages
Section titled “Related pages”- Sandbox security: the layers a sandbox pod has on every runtime
- Run agents under gVisor or Kata: install a runtime, select it, and check what it keeps on your nodes
- Class status: the fields and conditions a class reports