1966Dennis and Van Horn, on programming semantics
A capability is a reference that both names a thing and carries the right to use it. Holding one is the authority; there is no separate check against a list of who is allowed.
The consequence is that a program can act on exactly what it has been handed and nothing else, because there is no way to name anything it was not given.
1970s onwardsWhat the alternative does instead
The model that won attaches permissions to the resource and identity to the process. A program runs as a user, and it may touch anything that user may touch.
That is convenient and it means authority is ambient: it surrounds the program rather than being carried by it, and every action the program takes, including actions taken on somebody else's behalf, is backed by the full set.
1988The failure that has a name
The characteristic defect was described and named two decades after the model was proposed. A service holds authority for a legitimate reason. A caller asks it to do something, naming a target the caller could not reach alone. The service, using its own authority, obliges.
Nobody has been compromised and nothing has been broken into. The service was deputised and confused about whose authority it was exercising, and the model provides no way for it to tell.
Why it did not win
Two reasons, and the second is the durable one. Capability systems needed support through the whole stack, from hardware or the kernel up into the language, and partial adoption gives partial benefit.
And access lists match how organisations actually think. An administrator asks who may read this file, which is a question about a resource. A capability system answers a different question: what should this running thing be able to reach. The second is the better question and it is not the one anybody was asking.
1970s onwardsWhere it always existed
One capability system has been in continuous use the whole time, and it is not usually described that way. A file descriptor is an unforgeable reference that carries the right to use the thing it names, cannot be guessed, and can be passed to another process.
Which is why the standard advice for reducing a program's authority is to open what it needs before dropping privileges. That is capability practice, arrived at by necessity and not by design.
2010s onwardsWhat has returned
Sandboxing interfaces that let a process enter a mode where it can only use descriptors it already holds. Operating systems with capability designs formally verified. A module system for portable binaries in which a program receives its file system access as an explicit argument. Browser permission prompts. Delegated tokens instead of shared passwords. Hardware carrying bounded references.
Every one of those is the 1966 idea, arrived at again from a different direction by people solving an immediate problem.
The general shape
The pattern in this part again. A design that is better and requires coordinated adoption loses to one that is worse and requires none, and then reappears in pieces once the cost of the worse one is large enough to justify local effort.
What is different here is the timescale. Sixty years, and the reappearance is still partial.
1970s and 1980sWhat the machines that tried it showed
Several were built, and one of them was a commercial success for decades in business computing, with addressing where a pointer carried its own bounds and rights in hardware.
That matters because the model is often dismissed as academic. It was shipped, it was used by ordinary organisations for ordinary work, and its descendants were still being sold long after the machines that beat them technically had themselves been replaced.
Why partial adoption is the hard part
A capability discipline holds only if nothing can obtain authority by other means. One interface that resolves a name into a resource, one global table, one call that consults an identity rather than a handle, and the property is gone for the whole system.
Which is why the modern sandboxes are so restrictive: they work by entering a state where the naming interfaces are simply removed, and everything after that must have been opened before.
present dayWhat to take from it in practice
The usable rule does not require a capability system. Ask, of any component, what it can reach if it is subverted, and whether that set is larger than what it needs.
Wherever the answer is that it can reach everything its user can, the confused deputy is available, and the repair is to hand it specific references rather than to check permissions more carefully.
What it does not solve
Worth stating so the entry does not read as advocacy. Capabilities make delegation precise; they do not make revocation easy, and taking authority back from something you handed it to requires additional machinery.
They also move the difficulty into the design of interfaces: somebody must decide what each component ought to be handed, and doing that badly produces either a component that cannot work or one holding everything, which is where it started.
What we cannot verify
The original paper, the named failure and the machines that implemented the model are documented and can be read. Explanations of why the industry chose otherwise are reconstructions, and the commercial history of the machines involved is entangled with factors that had nothing to do with the model.
In short
- A capability names a thing and carries the right to use it, in one reference.
- The model that won makes authority ambient: it surrounds the program.
- The confused deputy is the characteristic defect, and it involves no break-in.
- It needed support through the whole stack, and answered a question nobody asked.
- A file descriptor is a capability, which is why opening before dropping works.
- Sandboxes, verified kernels and portable module systems are all rediscovering it.