JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Unikernels, Capabilities, and Confidential Computing

Three frontier ideas converge on one question: how small and how trustworthy can the thing running your code be? A unikernel collapses the whole stack into one tiny image, capability-based security replaces "who are you?" with "show me your token," and confidential computing shrinks trust until even the host operating system is shut out. This guide ties them together as the last rung of the ladder.

One question behind three frontiers

You have climbed a long way. You know what a system call costs because it crosses into the kernel, why a virtual address is not a physical one, how a hypervisor runs an OS on an OS, and from the verified-systems guide why a microkernel like seL4 keeps its trusted core tiny. This last guide is not a new mechanism so much as a direction. Three of the liveliest frontiers in systems — unikernels, capability-based security, and confidential computing — are all answering one question from different angles: how small, and how trustworthy, can the thing that runs your code be? Each one shrinks something we used to take for granted: the OS, the notion of identity, or the set of components you are forced to trust.

There is a thread running through all three, and it is worth naming up front because it is the moral of this whole rung. The smaller and more sharply bounded a system is, the easier it is to reason about — to test, to verify, to trust. A general-purpose OS is wildly capable, but its very generality is a liability: millions of lines of code, any of which could hold the bug that lets an attacker in. Each idea in this guide buys safety by removing generality. That is the same predictability-over-power bargain you met with real-time systems and with seL4's proof: you give up some convenience and some flexibility to get something you can actually reason about. Keep that trade in mind; it is the lens that makes all three ideas click.

Unikernels: collapse the whole stack into one image

Picture how a normal program reaches the hardware. Your code calls malloc() and open() in user space; each syscall traps into a huge general-purpose kernel that manages many processes, many users, a full file system, a TCP/IP stack, dozens of drivers. But a cloud service is usually one program. It does not need multiple users, or the ability to run other programs, or most of those drivers. A unikernel takes that observation to its conclusion: link your application together with just the OS pieces it actually uses — a slice of network stack, a memory allocator, a scheduler — into a single, self-contained machine image that boots directly on a hypervisor with no general-purpose OS underneath at all.

The consequences are dramatic and they all come from removing the user/kernel boundary. There is only one address space and one privilege level, so a system call is no longer a trap and mode switch — it becomes a plain function call within the image, which is genuinely cheaper. A unikernel image can be a few megabytes instead of hundreds, boot in tens of milliseconds, and present a tiny attack surface: there is no shell to drop into, no second process to pivot to, no unused driver to exploit. If your code does not link the file-system library, there is literally no open() in the image to attack. You compile away the parts you do not use, and the parts you do not ship cannot be turned against you.

Capabilities: unforgeable tokens instead of identity checks

Now shrink a different thing: the idea of identity. Think about how a normal OS decides whether you may read a file. You call open() on a path, and the kernel asks "who is this process, and do its credentials grant access to this object?" That is access control by identity — the system holds a list of who-may-do-what and checks you against it on every operation. It works, but it has a famous failure mode: the confused deputy. A privileged program (say a compiler that can write to a protected log) can be tricked by a less-privileged caller into using its authority on the caller's behalf, because the check is on the deputy's identity, not on whether this particular request should be allowed.

A capability flips this around. Instead of an identity that the system looks up in a list, a capability is an unforgeable token that both names an object and grants a specific right to it — "this token lets the holder read file X." To do something, you do not say "I am Alice, please check my permissions"; you present the token, and possessing it is the permission. You already know a humble version of this: a file descriptor is almost a capability. Once a process holds an open fd, it can read() from it without re-checking the path's permissions, and it can even hand that fd to another process over a Unix-domain socket — passing the right itself, not the identity. Capability-based security generalizes that: every right is a token, authority is what you hold rather than who you are, and you grant access by handing over a token, not by editing a global list.

Two properties make this powerful for security. First, it makes the principle of least privilege natural: a component holds tokens for exactly the objects it needs and cannot even name anything else, which closes the confused-deputy hole — to misuse authority you would have to be handed the token, and a careful program simply never hands it over. Second, it composes cleanly. seL4 from the previous guide is a capability-based microkernel for exactly this reason: when every kernel resource (a thread, a page of memory, an interrupt) is named only by a capability, the question "what can this component possibly do?" has a precise, enumerable answer — the set of tokens it holds — which is what made seL4's authority confinement provable. You also meet a small dose of this idea on ordinary Linux: dropping POSIX capabilities hands a process a narrowed bundle of powers, and seccomp restricts the very set of syscalls it is allowed to make at all.

Confidential computing: shut out even the host

Here is the most radical shrink of all — shrinking who you have to trust. Every protection so far assumes the kernel and the hardware are on your side: the kernel enforces memory protection, the hypervisor isolates VMs from each other. But run your workload on someone else's cloud and a hard question appears: do you trust the operator of that machine? The host OS, the hypervisor, and anyone with root on the box can, in principle, read the memory of the guest. For a bank or a hospital that is not paranoia; it is the threat. Confidential computing attacks this by using a hardware feature so that your data and code stay encrypted in memory and are decrypted only inside the CPU itself, where even the host kernel and hypervisor cannot look. The mechanism is a trusted execution environment (TEE), sometimes called an enclave or a confidential VM: the CPU maintains a protected region encrypted by a key that lives inside the chip and is never exposed to software outside it — not to the OS, not to the hypervisor, not to someone with a probe on the memory bus. Code inside a TEE runs at full speed on the real CPU, but every cache line written out to DRAM is transparently encrypted, so all the host can see is ciphertext. It is the inverse of virtual memory's usual model: there the kernel is all-powerful over a process's memory; here the goal is explicitly to make the kernel unable to read the protected memory it nominally manages.

But encryption alone leaves a gap: how do you, sitting at home, know your code is really running inside a genuine TEE on real hardware, and not in a simulator the operator built to harvest your secrets? The answer is remote attestation, and it is the piece that makes the whole thing usable. Before you send any secret in, you ask the enclave to prove itself: the CPU produces a signed report — a measurement (a cryptographic hash) of exactly the code and configuration loaded into the TEE, signed by a key the silicon vendor vouches for. You check that signature and that the measurement matches the code you expected, and only then do you establish an encrypted channel and hand over your data. Remote attestation turns "trust me" into "here is hardware-backed proof of exactly what is running," which is what lets you safely use a machine whose owner you do not trust.

Confidential computing, end to end:

  1. provision   host loads your code+data into a TEE region
                 (host can see only ciphertext in DRAM)
  2. attest      CPU signs a report = hash(code, config)
                 signed by a vendor-rooted key
  3. verify      you check the signature + that
                 hash == the code you intended
  4. seal        you open an encrypted channel into the TEE
                 and send the secret (key, data) ONLY now
  5. run         decrypt happens inside the CPU; host OS,
                 hypervisor, root user all see ciphertext

  trusted: CPU + your enclave code
  NOT trusted: host OS, hypervisor, operator, DRAM bus
The shape of a confidential-computing session. Attestation comes before you reveal any secret: you prove what is running, then seal a channel, then send data. The trusted base shrinks to just the CPU and your own enclave code — the host operating system and its operator are explicitly outside it.

Where the frontier is heading

These ideas are converging in practice, which is the real reason to learn them together. Modern cloud platforms run untrusted code in microVMs — stripped-down VMs that boot in milliseconds with a minimal device model, very much in the unikernel spirit of "ship only what you need." A microVM gives you the strong isolation of a hypervisor with a fraction of the startup cost and attack surface, and you will recognize the virtio interface and type-1 hypervisor machinery underneath from the virtualization guide. Layer a TEE over it and you get a confidential VM; restrict its powers with seccomp and capabilities and you have least privilege from the hardware up. From the very first guide in this rung you also met WebAssembly and Wasm runtimes doing a related job in software: a tiny sandbox with a capability-style interface (WASI hands a module explicit handles rather than ambient filesystem access). Minimal footprint, explicit authority, hardware-backed trust — the same three threads, braided together.

It is fitting that the ladder ends here, because these frontiers are also where the field's deepest argument plays out — the one named by the safety-versus-control debate. For decades, C let you do anything to memory, which is exactly what made systems programming both powerful and dangerous; you spent whole rungs learning undefined behavior, the buffer overflow, and the use-after-free precisely because that control comes with a body count of CVEs. Every idea in this guide pushes toward the other pole: take away some control — the ability to name any object, to read any address, to run as a fat general-purpose OS — in exchange for safety you can verify or even prove. That is the same trade Rust offers in a language, and seL4 offers in a kernel: not magic, not the end of all bugs, but a deliberate exchange of raw power for bounded, checkable trust.

So that is where you stand at the top of the ladder. You started not knowing what a pointer was; now you can read a confidential-computing attestation flow and see, underneath, the virtual memory, the file descriptors, the syscall boundary, and the trust boundaries you built up rung by rung. None of these frontiers are finished — TEEs are still hardening against side channels, unikernels are still earning their operational tooling, verified kernels are still small. That is not a weakness; it is the invitation. The frontier of systems is exactly where the question "how small and how trustworthy can it be?" still has better answers waiting to be built, and you now have the foundation to help build them.