Edera Object Capabilities: Privilege Without Credentials
Connection Is Not Authorization: Granting Privilege With Object Capabilities
Edera grants privileged operations to workloads as object capabilities (ocaps). A workload that needs one operation gets one socket for it. The socket is the only way to invoke that operation, and the broker re-checks the grant on every call. No network path is opened and no credential is handed to the workload.
Most container platforms answer a different question. Network policy decides which pods may open connections to which addresses and ports. The server on the other end then decides what the caller may do, usually by checking a token or key the caller carries, and that token works from anywhere the network lets it reach.
This is not a full object-capability system. By default, a workload in an Edera zone keeps its network access and any credentials it is given, so it still holds ambient authority. Capabilities apply only to the operations moved onto them, and for those operations the workload holds no credential.
Edera did not invent object capabilities. The model is decades older than containers, and this post starts there. It then covers what we built, how a capability call travels between zones, how it compares with network policy, credential-injecting proxies, OPA and the other tools it gets mistaken for, and what it does not replace.
How Kubernetes Network Policy Grants Access, Then Hands Off
Kubernetes NetworkPolicy works at OSI layers 3 and 4, on IP addresses and ports. A pod accepts every inbound and outbound connection until some policy selects it. The rules only take effect if the cluster's network plugin implements them, and the Kubernetes docs list TLS, logging of blocked connections, and targeting services by name as out of scope.
Cilium and service meshes add identity and layer 7 on top. Cilium derives a security identity from a pod's labels, and every pod with the same labels shares it. HTTP rules are enforced by an Envoy proxy on each node.
Istio gives each workload an X.509 certificate tied to its Kubernetes service account. Its AuthorizationPolicy matches on that identity, namespaces, HTTP methods and paths. A workload with no authorization policy accepts every request.
All three share one shape. A policy filters traffic toward an API the server already exposes, and the server decides what the caller may do from a credential the caller presents. That works for ordinary service traffic, but for privileged operations it leaves four gaps.
- The credential carries the authority. A registry token, kubeconfig or cloud key mounted into a pod works from any machine that can reach the server, so a stolen copy takes the authority somewhere the policy never sees.
- Identity comes from metadata next to the workload. Anyone who can set those labels or run a pod under that service account inherits the identity and everything allowed to it.
- The default is open. Kubernetes allows all traffic to a pod no policy selects, and Istio allows all requests to a workload with no policy, so safety depends on someone writing a policy for every workload.
- The unit of permission is the server's API. A policy can narrow which endpoints a caller reaches, but it cannot reduce an operation to one fixed command unless the server was built to offer exactly that.
Where Object Capabilities Came From: The Model Since 1966
In the object-capability model, a capability is a reference that both names a resource and grants the right to act on it. A process can only act on what it holds a reference to, and it only gets a reference by starting with one, creating the object itself, or being handed one. Nothing is granted because of who a process is or where it runs.
The idea of a capability comes from a 1966 paper, Programming Semantics for Multiprogrammed Computations. The name object capability came later. Since then the model has been built into hardware, operating systems and sandboxes, and several of them are in use today.
For the common misreadings of the model, Capability Myths Demolished (2003) is a good starting point. The name also collides with Linux capabilities such as CAP_SYS_ADMIN, which are a different thing and are covered further down.
For a privileged operation on Linux, the simplest such reference is a Unix socket. capsudo uses one to replace sudo. A daemon starts ahead of time already holding the privilege, binds a socket, and runs a command for whoever connects to it.
The caller passes its stdin, stdout and stderr over the socket. The command's output lands in the caller's terminal and its exit code comes back as the caller's own, so to the caller it looks like running the command locally.
Three properties follow, and they are the ones network policy does not give.
- The permission is the endpoint. A process that cannot open the socket cannot invoke the operation, and the caller holds no token that could be copied elsewhere.
- The provider sets the limits. It can fix the command, append or discard the caller's arguments, and discard the caller's environment, so even a fully compromised caller can only trigger the operation that was approved.
- The provider holds the secrets. Credentials stay with the process that does the work, not the process that asks for it.
What Edera adds is applying the model to workloads that run in separate virtual machines. The capability inside a workload is still a Unix socket. The process behind it can run in another zone, in the host daemon, or in a process the daemon starts, and the workload cannot tell which.
How Edera Brokers Every Capability Call Between Zones
Edera runs each workload in a zone, a virtual machine with its own kernel. capsudo assumes the caller and the provider share a kernel, so we wrote capsudo-rs, an open-source reimplementation that carries the same session between zones. To the caller it still looks like running a command locally, with its own terminal, output and exit code.
A workload declares the capabilities it needs alongside its image. A provider declares what it offers and how narrowly, and it can fix the command and environment and ignore anything else the caller sends. The workload gets a local socket for each capability it was granted and nothing for the rest.
Zones cannot reach each other's capabilities directly. An agent in each zone presents granted capabilities to its workloads, and every call goes through the Edera daemon on the host, which acts as the broker. It checks the grant on each call and routes it to the provider, in another zone or on the host itself.
The broker identifies the calling workload by the isolation boundary the call came through, not by anything the workload sends. If a capability a workload depends on is unavailable, the workload does not start.

The workload holds a socket and no credential. The provider holds the credential and runs only the operation it offers.
Edera uses this for its own privileged paths. Since 1.12.0, image fetch and pack run in their own capability-scoped processes outside the daemon. SPIRE node attestation is a capability, and so is workload certificate issuance from SPIRE, a static CA, or a customer's own CA through an adapter.
SPIRE support used to depend on giving a privileged zone the daemon's whole control API, and Edera 1.13.0 removed that API in favor of named capabilities. Object capabilities shipped behind a feature flag in 1.11.0 and have been always on since 1.13.0.
Object Capabilities vs Network Policy: Replacing the Credential
Network policy starts from a network where everything can reach everything and removes paths. The capability broker starts from nothing and adds one operation at a time, but it sits beside the network rather than replacing it. The table compares the two for a single privileged operation.
The two are not exclusive. A workload can still serve HTTP to other workloads under network policy and a service mesh. Object capabilities cover the narrower set of calls that carry privilege, such as pushing an image, issuing a certificate, attesting a node, or reading a trust bundle.
For those calls, the network model fails in a specific way. Once a credential leaves the pod, every control that depended on the pod's address or labels stops applying, and the credential's full scope goes with it.
Object Capabilities vs OPA, RBAC, and Linux Capabilities
Most security tools in a cloud-native stack answer whether a request is allowed, or limit what a process can do on its own machine. An object capability does neither. It is a reference to one operation that someone else performs, and the table shows where each familiar tool differs.
The common thread is where authority sits. Most tools in the table decide about a caller, limit the caller's own process, or give the caller something to hold. A credential-injecting proxy keeps the plaintext secret out of the caller. A capability leaves the caller nothing portable for that operation. Neither takes away authority the caller already has by other routes.
The Limits of Object Capabilities: What They Do Not Replace
By default, Edera is not a pure capability system. In a pure one, capabilities are the only way to reach anything. A default Edera workload still has its network access, whatever credentials it is given, and every API those credentials open, and capabilities alone take none of that away.
That access can be closed. A zone launched with networking disabled (--network-backend none) has no network path at all, and HTTP access to a specific endpoint can then be granted as a capability with capcurl. With no credentials mounted either, capabilities become the workload’s only route to outside services, which is close to the pure model.
The gain is limited to the operations moved onto capabilities, so it grows with how much privileged access moves there. Where a workload keeps another route to the same service, the capability works like a brokered credential, not a capability in the classic sense.
They do not replace network policy for application traffic. Services that talk HTTP or gRPC to each other still need network policy, mTLS and their own authorization. Capabilities are for the smaller set of operations that carry privilege.
A capability is only as narrow as the provider makes it. One that does not fix its command lets the caller run any command in the provider's workload.
The unit of attribution is the workload. Any process inside a consuming workload that can open the socket can use the capability, and the broker records the call as coming from that workload.
Offering a capability is as privileged as creating a workload, because a new provider can take over an existing capability. Access to create workloads is the boundary that matters.
The broker is a shared point that every cross-zone call passes through, which makes it a denial-of-service target. It caps how much any one zone can hold open or make it buffer.
Grants are declared, not passed around. The classic model lets any holder hand a reference to someone else. Edera has no runtime API for that, and every grant goes through a workload spec the daemon admits and re-checks on every call.
The same mechanism lets more of the host’s privileged work move into zones later, without changing the workloads that use it.

-3.avif)