Runtime Confinement and the Least-Privilege Workload — Capability Dropping, Syscall Filtering, and the Read-Only Root Discipline
Last week confined where the workload may talk. This week confines what it may do.
§ IFrame
Last Wednesday closed the network seam. Mutual TLS proved each end of a connection, segmentation decided which workloads could talk, and authorization bounded what a permitted caller could ask for. An attacker who lands in the lowest-value agent now finds the cluster's interior segmented against him: the workloads two hops away in the call graph are unreachable in one hop on the wire. The network has been told to trust nothing for being inside.
There is a seam the network discipline never touches. When the attacker lands in that routing agent, he does not only inherit a network position. He inherits a running process, on a real Linux kernel, with whatever privileges the container was started holding. He can write to the filesystem the agent runs on. He can open raw sockets if the container kept the capability. He can call any of the three-hundred-odd Linux syscalls the kernel exposes, including the ones a language-model agent will never legitimately need. Segmentation governs where the workload may talk. It says nothing about what the workload may do on the machine it runs on.
This lesson governs the doing. Three named techniques carry it: capability dropping, which strips the container of kernel privileges it never uses; syscall filtering, which narrows the kernel surface the process may call at all; and the read-only root discipline, which denies the running process the ability to rewrite its own filesystem. The rule underneath is the same rule that ran last week, turned inward one ring: deny by default, permit by name. The network version asked which connections may exist. The runtime version asks which kernel privileges may exist. One discipline, three surfaces, one ring deeper than the wire.
§ IIFoundations
A container is not a virtual machine. The phrase invites the wrong mental model, because a virtual machine carries its own kernel and a container does not. Every container on a host shares the one host kernel. The isolation a container provides (separate process tree, separate filesystem view, separate network namespace) is a set of kernel features wrapped around a process that is, underneath, an ordinary process on the host. The boundary between a container and its host is not a hardware wall. It is a configuration, and the default configuration is more generous than any single workload needs.
Two kernel mechanisms decide most of what a process may do, and both predate containers by years. The first is capabilities. The old Unix model had one privileged user, root, who could do everything, and every other user, who could do almost nothing. Linux capabilities break root's omnipotence into roughly forty discrete privileges granted or revoked one at a time. CAP_NET_BIND_SERVICE lets a process bind a port below 1024. CAP_NET_RAW lets it craft raw packets. CAP_SYS_ADMIN, the most dangerous, grants a sprawling set of administrative operations that amount to most of root. A runtime grants a default capability set chosen for compatibility, not for any one workload's actual need.
The second mechanism is the syscall interface itself. Every operation a process asks the kernel to perform (open a file, fork a child, change a user ID, load a kernel module) is a syscall, and the kernel exposes over three hundred of them. A language-model inference agent uses a few dozen. The other two hundred and seventy are surface the agent never touches and an attacker inside the agent very much wants. seccomp lets the operator hand the kernel a list of which syscalls a process may make, and the kernel kills the process if it calls one outside the list. Newman's security chapter frames the governing idea: grant a component the least privilege it needs, and nothing beyond it, so a compromise inherits only what the component legitimately held.
§ IIIMechanism
Capability Dropping — Strip, Then Add Back
The default capability set begins from permit and asks the operator to subtract. Invert it. Drop ALL, then add back only the capabilities the workload provably needs. A container that drops everything and adds nothing holds none of root's kernel privileges even if it becomes root inside its namespace. Keep an unused capability and nothing breaks, so nothing flags it; drop a needed one and the workload fails loudly in testing. The set that survives to production is the set a broken test forced the operator to justify.
Syscall Filtering — Narrow the Kernel Surface
Capabilities gate privileged operations; seccomp gates the whole syscall interface, including the ordinary calls a capability set never mentions. Record every syscall the workload makes across a full exercise of its behavior, compile that profile into a filter that permits exactly those calls, and the process can no longer reach a syscall it was never observed to need. An attacker who reaches for ptrace or the mount calls hits a syscall the filter does not permit, and the kernel terminates the process before the call returns.
Read-Only Root — Freeze the Filesystem
A writable root filesystem lets a compromised process drop a binary, rewrite a config, or stage a payload for persistence. Mount root read-only and the process can read its own code but cannot rewrite it. The data the workload legitimately mutates gets an explicit, named writable mount; everything else is frozen. An attacker who lands in a read-only-root container finds the most basic move — writing a tool to disk — fails, and he is reduced to what he can do in memory.
The three confinements compose into one sentence the operator can hold: a running workload may use only the kernel privileges it was named, call only the syscalls it was recorded making, and write only the paths it was given. Strip any one of the three and the attacker walks through the clause it left open.
drop ALL and adds back by name fails closed: every privilege the operator forgot to add is missing, the workload breaks loudly in staging, and the operator adds exactly the one it needs. Fail closed. A broken test costs an afternoon; an unconfined process costs the host.
§ IVWorked Example
A fleet runs the five-workload inference path from last week: an ingress gateway, a routing agent, a retrieval agent, a vector store, and a model server. Last week the fleet segmented the network between them. This week it confines each process. Every workload starts with drop ALL capabilities, a recorded seccomp profile, a read-only root filesystem, and a single named writable mount for the one directory it writes. Walk the same attacker through, one ring deeper than the wire.
The attacker compromises the routing agent through a dependency vulnerability, exactly as before. Last week, segmentation confined him to the one network flow the routing agent legitimately held. This week, runtime confinement narrows what he can do inside that foothold. He tries to write a reverse-shell binary to disk: the root filesystem is read-only, and the write fails. He tries to open a raw socket to scan the host network from inside the namespace: CAP_NET_RAW was dropped, and the socket call returns a permission error. He tries ptrace to read secrets out of a neighbor's memory: the syscall is not in the recorded profile, and the kernel kills his process. Each escalation he reaches for is a privilege the workload never used, and each one was stripped before he arrived.
Compare the same compromise on a default-configured container. The attacker lands in the routing agent and finds a writable root filesystem to stage tools on, a default capability set larger than the workload ever used, and the full syscall interface open. He writes his persistence binary, uses a kept capability to manipulate the namespace, and probes the host kernel through syscalls the workload never made. The foothold becomes a platform. The difference between the two outcomes is three confinements and one inverted default.
The honest cost is the recording work. A custom seccomp profile takes an exercise of the workload to record and a staging cycle to validate, and a read-only root forces the operator to name every writable path. The fleet pays this once per workload type for a defense that holds on every running instance. A multi-agent system, where the same agent image runs in many replicas, is exactly the place the recording cost pays back.
§ VConnection to Prior Lessons
Three earlier β-Trust lessons set up this one, and the relationship to one of them is worth stating precisely.
Runtime threat detection (2026-05-28) instrumented the workload with eBPF and Falco to observe what the process does and alert when it does something forbidden. Detection watches; confinement prevents. A detection pipeline tells the operator a process called an unexpected syscall after it happened; a seccomp filter stops the call before it returns. The honest posture runs both: confinement closes the privileges the workload never needs, and detection watches the narrow surface that remains for misuse of the privileges it does need.
Supply-chain provenance (2026-06-03) proved where the running bytes came from. Provenance assumes the image might be malicious and refuses to run an unverified one. Confinement assumes the image is trusted but might be exploited at runtime through a vulnerability provenance could not catch, because it was in code the legitimate maintainer signed. An attacker who exploits a real CVE in a properly signed image walks straight past provenance and lands in the runtime, where confinement meets him.
Zero-trust networking (2026-06-10) confined the attacker's reach across the network; this lesson confines his reach into the host. The two are the same default-deny rule applied to two resources: the network policy denies connections not named, the capability set and syscall filter deny privileges not named. Together they mean the attacker can neither talk to a workload the design did not connect him to nor do anything to the host the workload did not need. The blast radius is bounded on both axes at once.
§ VIConnection to Today's Dev + Cert Lessons
The cert lesson today is the hands-on Kubernetes form of this discipline. It writes the securityContext block directly: runAsNonRoot, capabilities.drop: ["ALL"], seccompProfile, readOnlyRootFilesystem, and the CKS extension into AppArmor profiles and the Pod Security Standards that enforce the set cluster-wide. Where this lesson named the three confinements, the cert lesson writes the YAML and debugs the workload that broke because a profile was one syscall too tight.
The dev lesson carries the same least-privilege discipline into the Node.js process that runs an agent. Node's permission model is the runtime's own capability drop: a process started with the permission flags off cannot read the filesystem, spawn a child, or open a worker unless the operator named the grant, which is drop ALL, add back by name expressed in a language runtime rather than a kernel. TypeScript's branded types then make a capability a value a module cannot fabricate. The kernel, the cluster, and the language runtime are three machines running one rule: hold the least privilege the work requires, and deny by default everything it does not.
§ VIIClosing
A confined workload is not a workload the operator trusts less. It is a workload the operator has measured. Capability dropping measures which kernel privileges the work uses and strips the rest. Syscall filtering measures which calls the work makes and blocks the rest. The read-only root measures which paths the work writes and freezes the rest. Each confinement is a measurement made once, in staging, where a wrong measure costs an afternoon.
A default-configured container tells the attacker that one foothold is a full Linux process with root's privileges and a writable disk. A confined container tells the attacker that one foothold is one foothold, stripped to exactly the privileges the legitimate workload needed and not one more. Measure what the workload needs; deny the kernel everything else; trust no privilege you cannot name.
Filed 2026-06-17 Fajr ANCHOR; Wed × β × Web(JS+TS) × CKA+CKS crossing under cert-prep extension v3.1