Edera Object Capabilities: Privilege Without Credentials

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.

SystemWhat It IsWhat a Capability Is There
KeyKOSWhat It IsOperating system for IBM S/370 mainframes, developed from the mid-1970s.What a Capability Is ThereThe access model the whole system was built on.
seL4What It IsMicrokernel.What a Capability Is ThereAn unforgeable token that permits access to one kernel object.
CapsicumWhat It IsSandbox framework, first shipped as experimental in FreeBSD 9.0.What a Capability Is ThereA file descriptor that carries fine-grained rights.
FuchsiaWhat It IsOperating system.What a Capability Is ThereA handle to a kernel object, with rights that say which operations are allowed.
CHERIWhat It IsProcessor extension, on Arm Morello and RISC-V.What a Capability Is ThereA hardware capability used for memory protection and compartmentalization.
capsudoWhat It IsPrivilege delegation for Unix.What a Capability Is ThereA socket that runs one privileged command.

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.

Diagram titled “Every capability call goes through the broker on the host,” showing a top-to-bottom flow through three stacked boxes. The top box, labeled Consumer Zone (VM), contains a Workload that holds a socket and holds no credential. An arrow points down to the middle box, labeled Host, containing the Edera Broker, which checks the grant and routes the call. A second arrow points down to the bottom box, labeled Provider (zone or host), containing the Provider Workload, which holds the credential and runs one fixed operation.

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.

QuestionNetwork Policy and Service MeshEdera Object Capabilities
What is grantedNetwork Policy and Service MeshReaching an address and port, or HTTP methods and paths on a server.Edera Object CapabilitiesOne named operation.
Where the authority livesNetwork Policy and Service MeshIn a credential the caller presents to the server.Edera Object CapabilitiesIn the provider. The caller holds only a socket.
How the caller is identifiedNetwork Policy and Service MeshIP address, pod labels, or a service-account certificate.Edera Object CapabilitiesThe zone and workload the call came from, as the host sees them. The calling process cannot claim to be another.
What happens with no policyNetwork Policy and Service MeshTraffic is allowed in Kubernetes and Istio.Edera Object CapabilitiesThe broker refuses it. A workload that was granted nothing has no socket to call, but its network access is unchanged unless the zone runs without networking.
What a stolen secret is worthNetwork Policy and Service MeshA copied token works from anywhere that can reach the server.Edera Object CapabilitiesThe caller holds no secret for this operation. The socket exists only inside the granted workload, so it is worthless outside it but usable by any code inside it.
What a compromised caller can doNetwork Policy and Service MeshAnything its credential allows on the server's API.Edera Object CapabilitiesThrough the capability, only what the provider allows. With a fixed command, only that command.
Which path the call takesNetwork Policy and Service MeshThe cluster network.Edera Object CapabilitiesA private channel between the zone and the host. No network path between zones is opened.
When a dependency is missingNetwork Policy and Service MeshThe connection fails when it is first used.Edera Object CapabilitiesThe workload is not started.
Where the rules liveNetwork Policy and Service MeshPolicy objects, enforced by the network plugin or a proxy on each node.Edera Object CapabilitiesThe workload spec, enforced by one broker on the host.
What the provider learns about the callerNetwork Policy and Service MeshWhatever the caller's credential says.Edera Object CapabilitiesThe zone and workload, set by the broker.

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.

ToolWhat It DoesHow It Differs from an Edera Object Capability
Credential-injecting proxies, such as tokenizerWhat It DoesThe client seals a third-party secret with the proxy's public key and sends it with each request. The proxy decrypts it and injects it, so the client never holds the plaintext.How It Differs from an Edera Object CapabilityThe closest existing pattern. The client still holds something portable, the sealed secret plus its credential for the proxy. That pair works from anywhere that can reach the proxy, unless it is tied to one machine as Fly's fly-src mode does. A capability leaves the caller nothing to take elsewhere, identifies it by its VM's channel to the host, and can run any command rather than only forward HTTP.
Open Policy Agent (OPA)What It DoesA policy engine. Software sends it structured input and gets back a decision, computed from policies written in Rego.How It Differs from an Edera Object CapabilityOPA decides. It does not create a path to anything, hold a secret, or run the operation. A capability provider could ask OPA before acting, so the two can be layered.
Kubernetes RBACWhat It DoesGrants users and service accounts verbs on Kubernetes API resources. Permissions are additive and have no deny rules.How It Differs from an Edera Object CapabilityRBAC covers the Kubernetes API and rides on a credential the caller holds. A capability covers any operation and gives the caller nothing to present.
Linux capabilitiesWhat It DoesSince Linux 2.2, root's privileges are split into units such as CAP_NET_ADMIN, held per thread.How It Differs from an Edera Object CapabilitySame word, different idea. A Linux capability is a privilege that applies to everything the process touches, and it cannot be passed to an unrelated process as a reference. An object capability names one object or operation.
sudo and setuid binariesWhat It DoesThe calling process itself becomes root or another user, according to rules on that machine.How It Differs from an Edera Object CapabilityThe caller never gains the privilege. A provider that already holds it runs a fixed command on the caller's behalf. capsudo is the object-capability version of sudo.
seccomp and AppArmorWhat It DoesThe kernel limits which system calls, files and resources a process may use.How It Differs from an Edera Object CapabilityThese take ability away from a process. A capability adds one operation, served from somewhere else. Edera uses both, with seccomp and AppArmor confining the workload and capabilities as the controlled way out.
SPIFFE, SPIRE and mesh mTLSWhat It DoesGive each workload a short-lived cryptographic identity, as an X.509 certificate or JWT, that servers check.How It Differs from an Edera Object CapabilityAn identity says who the caller is, and each server still decides what that identity may do. In Edera, SPIRE attestation and certificate issuance are themselves served as capabilities.
Secrets managers such as VaultWhat It DoesStore secrets and issue them, often short-lived, to authenticated clients.How It Differs from an Edera Object CapabilityThe secret still ends up in the caller's memory. With a capability, it stays with the provider, which can fetch it from a secrets manager itself.

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. 

Cute cartoon axolotl with a light blue segmented body, big eyes, and dark gray external gills.

You know you wanna

Let’s solve this together