6  Capability-Based Access Control

Unforgeable Tokens of Authority, Permission Flags, Delegation, and Revocation

security
access-control
iot
Keywords

capability-based access control, object capability, permission flags, capability bitmask, delegation, confused deputy, least authority, IoT authorization

6.1 Overview: Authority You Hold, Not a Role You Have

Sometimes the easiest permission to reason about is not a name on a list. It is a key in the holder’s hand: this token opens this door, for this action, until this limit. Capability-based access control starts from that simple picture and then asks the hard IoT questions: can the key be forged, copied, delegated, narrowed, or taken back?

Most access control asks the system a question: who are you, and does your role permit this? Capability-based access control turns that around. A capability is an unforgeable token that both names a specific object and carries the operations allowed on it. Holding the capability is the permission. The system does not look you up in a list; it checks the token you present.

Shield Shelly, the security guide

Shield Shelly

“A capability is a claim until someone shows the token resists forgery and can still be taken back.”

Here she reads capabilities the way she reads sessions: what the holder can do, how far it can travel, and how it gets revoked.

The clearest analogy is a physical key. A key to room 12 does not care who you are – whoever holds it can open room 12, and they can hand it to someone else. A capability is a key for a particular action on a particular thing. This is fundamentally different from a guest list, which is checked against your identity at the door. A capability is the ticket you carry; an access-control list is the list the doorkeeper holds.

If you only need the intuition, this layer is enough: a capability is a held, unforgeable token that grants a specific right on a specific object. Because authority travels with the token, capabilities must be impossible to forge, they can be delegated by handing them on, and – the catch – a token already in someone’s hands is harder to take back than an entry in a list. Start simple: decide exactly what object and action the holder needs, then make the token narrow enough that losing it does not unlock the whole fleet.

Why does this matter for IoT? Capabilities express fine-grained, per-object rights that roles struggle with: read every sensor but write only the temperature setpoint, or open the trunk but never start the engine. They allow one device to delegate a narrow slice of its authority to a neighbor without a central server in the loop. And as compact permission flags they cost almost nothing in memory, which suits constrained devices.

6.1.1 The Key-in-Hand View

  • Unforgeable token: Possession grants the right, so the token must be impossible to forge – protected by the runtime or signed cryptographically.
  • Object plus rights: A capability designates a specific object and the operations allowed on it, not a broad identity label.
  • Delegable, but sticky: A holder can pass a capability (or a narrower subset) onward. The trade-off is that revoking it is harder than deleting a list entry.

6.1.2 Everyday IoT Examples

  • A valet key for a car is a capability subset: it can drive and park but not open the trunk or the glovebox.
  • A shareable, time-limited code that opens only the front door – and nothing else – is a capability, not a role.
  • “This token lets the holder read sensor 42 until noon” is a complete capability claim; “this user is an admin” is a role claim that still needs a separate permission lookup.

6.1.3 Overview Knowledge Check

If you can explain why authority travels with a held token, you have the core idea. Continue to Practitioner to represent capabilities, compose them, and choose when the key-in-hand pattern is better than another role.

6.2 Practitioner: Represent, Compose, and Choose

In practice, fine-grained rights are often represented as permission flags – independent bits, each standing for one capability such as read, write, execute, or audit. A composite “role-like” set is just several flags combined, and an access check confirms that all required bits are present, not merely some. The appeal is precision: you grant exactly the rights needed and nothing more, and on a constrained device the whole set fits in a couple of bytes.

6.2.1 Base, Ceiling, and Elevation

A robust design distinguishes a user’s or device’s base capabilities, granted by default, from its maximum capabilities, an absolute ceiling it can never exceed even when temporarily elevated. A canElevate flag controls whether elevation is allowed at all. When a sensitive action is needed – an emergency shutdown, a firmware write – the holder elevates specific capabilities for a short, time-boxed window, gated by extra authorization such as a supervisor’s approval. This is cleaner than swapping roles or minting a temporary admin account, because the audit trail shows exactly which extra rights were used, when, and under whose approval.

Shelly’s Access Ledger

  • Who: the holder elevating specific capabilities for a short, time-boxed window.
  • What: elevation can never exceed the maximum ceiling, even temporarily.
  • Proof: the audit trail names exactly which extra rights were used and who approved them.

6.2.2 Choosing Among RBAC, Capabilities, and ABAC

Model Best When Strength Watch Out For
RBAC Stable job categories with a small number of roles. Simple to set up, reason about, and audit. Role explosion when cases need many narrow roles.
Capability-based Per-object custom rights, delegation, or tight memory. Precise least authority; cheap flags; decentralized sharing. Revocation of tokens already handed out.
ABAC Decisions depend on context (time, location, state). Expressive, policy-as-code, scales by attribute. More complex to author and evaluate.

6.2.3 Worked Example: Shift Reassignment Without Role Explosion

Picture an industrial control room where operators rotate across shifts and certification levels. With pure RBAC, every combination tends to spawn its own role – a day-shift level-three role, a night-shift level-three role, and so on – until the role list is unmanageable. With capabilities, you instead edit a single operator’s granted rights when their shift or certification changes, leaving the resource definitions untouched. The most sensitive action, an emergency shutdown, sits at the operator’s ceiling and is reachable only by elevation that requires a second person’s approval. The capability model captures “who may do exactly what, right now” without a combinatorial role table.

6.2.4 Capabilities in the Physical World

Digital vehicle keys are a familiar illustration. A shared or valet key is an attenuated capability: it can drive and park but cannot open the trunk or exceed a set speed, while the owner’s key carries the full set. The reason such systems must be built carefully is instructive: early keyless-entry systems relied on weak proprietary ciphers that security researchers were able to clone, which is exactly why a modern capability must be cryptographically strong as well as fine-grained. A capability that can be forged or copied is no capability at all.

6.2.5 Practitioner Knowledge Check

If you can represent rights as flags, gate elevation by a ceiling, and choose the model by need, you can stop here. Continue to Under the Hood for unforgeability, delegation, and the revocation trade-off.

6.3 Under the Hood: Unforgeability, Delegation, and Revocation

The deeper layer explains what makes a capability actually work and where the model breaks. Two properties carry the whole design: the token must be impossible to forge, and the system must have an answer for taking authority back.

6.3.1 The Bit Mechanics

When capabilities are represented as flags, each permission is an independent bit position, not a step in a ladder – setting the fourth bit does not imply the first three. Composite sets are built by OR-ing flags together. An access check is conjunctive: the granted set must contain every required bit, which is the bitwise test (granted & required) == required. This compactness is why the model fits microcontrollers, where a full permission set is a single small integer.

Shelly’s Access Ledger

  • Who: whoever holds the granted bitmask presents it for every check.
  • What: flags are independent bits, not a ladder – the fourth bit implies nothing about the first three.
  • Proof: the check is conjunctive – every required bit must be present, not just one.

6.3.2 Unforgeability Is the Whole Game

Because possession grants authority, a capability is only safe if an untrusted holder cannot forge or alter it. There are two established ways to guarantee that. The first is a protected reference, where the runtime or kernel hands out and mediates the token so it can never be fabricated – Unix file descriptors and capability-based kernels such as seL4 work this way, and a process can pass a descriptor to another process as a genuine delegation. The second is a cryptographic token, where the capability is signed or authenticated (for example a macaroon or a pre-signed, time-limited URL) so the issuer can verify it was neither forged nor tampered with. A capability that is merely a plain string of flags, with nothing protecting it, is forgeable and therefore worthless.

6.3.3 Where the Rights Live, and the Revocation Trade-Off

A central design question is whether the rights travel with the client or stay on the server. If you place the permission flags in a client-held token, that token must be cryptographically signed – otherwise the client edits its own permissions – and even then it remains valid until it expires, so revoking it early requires extra server-side state such as a denylist or an introspection call. If instead you hand the client only an opaque reference (a session identifier) and keep the rights server-side, revocation becomes instant on the next request, but you have moved back toward an access-control-list lookup keyed by identity. This is the honest reading of the common warning against putting permission flags in client tokens: the issue is not that holder-borne authority is wrong – that is the essence of capabilities – but that bearer tokens must be unforgeable and are hard to revoke. Choose short lifetimes plus a revocation list when authority lives client-side; choose server-side rights when you need instant revocation.

6.3.4 Delegation, the Confused Deputy, and Ambient Authority

Delegation is a defining strength: a holder can pass a capability, or an attenuated subset of it, to another principal, enabling decentralized authorization with no central gatekeeper. Capabilities also resist the confused-deputy problem, in which a privileged program is tricked into misusing its broad authority on an object an attacker names. Because a capability bundles the object designation with the authority, the caller must supply the capability for the specific object, so a deputy cannot be steered onto something it was not given. The danger to manage is the opposite: ambient authority, where capabilities are inherited automatically and broadly. An over-broad inherited privilege – the Linux CAP_SYS_ADMIN capability is close to full root – undermines least authority. Grant the narrowest capability explicitly rather than relying on inherited power.

6.3.5 Audit as Categorized Events

A capability system should record categorized audit events – access attempted versus granted, elevation requested, and denials – rather than flat log lines. Categorized events let monitoring raise alerts automatically (a burst of denied elevations is a probing signal) and make compliance forensics tractable.

6.3.6 Mechanisms and Failure Modes

Mechanism What It Guarantees Evidence to Request Failure Mode If Weak
Unforgeable token Holders cannot fabricate authority. Kernel-protected references or signed tokens. Plain flag strings let a client forge permissions.
Conjunctive check All required rights must be present. A bitwise all-bits-match test, tested with negatives. An any-bit match grants access on a partial right.
Attenuated delegation Shared authority is never wider than the original. Delegation that can only narrow, never widen, rights. Unbounded delegation escalates privilege.
Revocation state Authority can be withdrawn before expiry. Short lifetimes plus a denylist, or server-side rights. A bearer token stays valid until it expires.
Least ambient authority Programs hold only the authority they were given. Narrow explicit grants, no broad inherited capabilities. Over-broad inherited rights enable confused-deputy abuse.

6.3.7 Common Pitfalls

  1. Unsigned capability flags in client tokens. If the token is not cryptographically protected, the client simply forges its own rights.
  2. Assuming bearer tokens revoke instantly. A signed client-held capability lives until expiry unless you add a denylist or introspection.
  3. Over-broad ambient authority. Capabilities like near-root system privileges should never be inherited by default.
  4. Treating flags as a hierarchy. Bits are independent; one capability does not imply the ones below it.
  5. No revocation path at all. Without revocation, a capability system can be weaker than a simple list it could otherwise improve on.

6.3.8 Under-the-Hood Knowledge Check

At this depth, a capability is a precise, held authority that is only as good as its unforgeability and its revocation story. Represent rights as independent flags, protect the token by the runtime or by cryptography, delegate by narrowing, and decide deliberately whether authority lives with the client or the server. A trustworthy review checks that forged tokens are rejected, that delegation cannot widen rights, and that revocation actually works.

6.4 Summary

  • A capability is an unforgeable, held token that designates a specific object and the operations allowed on it; possession is the permission, in contrast to an access-control list checked against identity.
  • Fine-grained rights are commonly represented as independent permission flags, composed with bitwise OR and checked conjunctively so that all required bits must be present.
  • Separate base capabilities from a maximum ceiling, and grant sensitive rights only through short, time-boxed elevation with extra authorization, which keeps a clean audit trail.
  • Choose capabilities for per-object custom rights, delegation, and constrained memory; choose RBAC for stable categories and ABAC for context-dependent decisions.
  • Unforgeability is essential: protect capabilities either as runtime or kernel-mediated references (like file descriptors) or as signed cryptographic tokens (like macaroons); plain flag strings are forgeable.
  • The revocation trade-off is central: client-held signed capabilities stay valid until expiry unless you add a denylist or introspection, while server-side rights revoke instantly but resemble an ACL lookup.
  • Capabilities support attenuated delegation and resist the confused-deputy problem, but over-broad ambient (inherited) authority undermines least authority.
  • The fabricated metrics sometimes attached to vehicle examples are unnecessary; the durable lesson is that a capability must be cryptographically strong and fine-grained, since a forgeable capability is worthless.

6.5 Key Takeaway

Capability-based access control puts precise, least authority in the holder’s hands as an unforgeable token. Make the token impossible to forge, let delegation only narrow rights, and decide up front where authority lives: client-side for decentralized sharing with short lifetimes and a denylist, or server-side when you need instant revocation. A capability you cannot protect or revoke is not access control.

6.6 See Also