A normal process on a normal operating system has ambient authority. It
runs as a user, and it can reach anything that user can reach. open() takes a
path, and whether the call succeeds comes down to checking the process's
identity against the filesystem's permissions.
That's the model almost all software is written against, and it's why a compromised process is so dangerous: it inherits everything its user could ever do. Hand a contractor your front door key and they have the run of the house, including the rooms you never mentioned.
WASI takes the other approach.
Handles, not paths¶
In a capability model, a module can't name a resource it hasn't been given. There's no global namespace to reach into. To open a file in a directory, the module has to be holding a handle to that directory already, and from a handle it holds it can only derive handles with equal or lesser authority.
The practical consequence: a WASM module handed a handle to /var/data
cannot construct a path to /etc/passwd. Not denied; unable to express the
request in the first place. There's no ambient root to traverse from. The
contractor gets a key cut for one room and no idea the corridor exists.
Why this beats a sandbox¶
Sandboxes usually work by interposing on a syscall boundary and deciding what to allow: seccomp filters, LSM hooks, AppArmor profiles. They're policy applied to a program that's still asking for the whole world.
A capability system changes what the program can ask for, and the difference shows up in the failure modes. A policy fails at its gaps: a denylist fails open outright, and even a strict allowlist still permits a vocabulary of syscalls whose combinations nobody enumerated. Capability systems fail closed, because authority nobody mentioned was never granted.
It also makes the authority auditable. What a module can do is the list of handles it was given, and a list is a thing you can sit and read.
Where the ecosystem is¶
Dates need care here. Researching this produced three mutually contradictory dates for the same WASI release across different write-ups. One source corrected another about whether a February date referred to previews landing in Wasmtime or to the ratified specification. The secondary coverage of WASM is unusually unreliable, apparently because it's a popular SEO topic.
So rather than repeat a date we can't stand behind: the component model and WASI's versioning are both moving, the async work is the significant recent addition, and anyone who needs a current answer should go to the specification repositories and the Bytecode Alliance's own records directly.
What this makes possible¶
The capability model plus a portable binary format gets you something that has not existed before: running somebody else's code without reviewing it for what it can reach. What it does with the authority you hand it still wants a look; the list of handles is the review's scope, not its replacement.
Consider a plugin. Today, extending a product with third-party code means either trusting the author, reviewing every release or running it in a container with an operating-system userland and runtime footprint attached. With WASI the plugin gets a handle to the one directory it needs and nothing else, can start much faster, and the authority it holds is a list you can print on a receipt. That makes opening a plugin ecosystem to strangers a bounded risk rather than an act of faith, bounded by the soundness of the host runtime. That is the difference between a product with twelve integrations written by the vendor and one with four hundred written by its users.
The same shape applies to multi-tenancy. If isolation costs microseconds rather than milliseconds, you can afford one instance per request rather than one per tenant. A whole category of bug stops being possible: the cross-tenant data leak caused by state left in a long-running process, which is the bug that ends companies. That class goes because no process outlives the request; bugs in the host runtime and side channels are not in the bargain.
For engineering more broadly, the toil that goes away is the sandbox audit. Right now, working out what a seccomp profile permits is an afternoon with a strace log and a hopeful expression. Working out what a WASI module permits is reading the list of handles the host passed in. We would rather review a list than enumerate badness, and so would you.
And it travels. A module gets the same declared authority in a server, an edge node and a browser tab. That matters most for the places with the worst infrastructure: compute that can run on a cheap box in a clinic with intermittent power, and run as the same module unchanged in a datacentre, holding the same declared authority in both. The code enforcing that authority is each runtime's own, and that is where the scrutiny moves.
Where it falls down¶
- Capability discipline has to go all the way down. A host that hands a
module a handle to
/has a capability system in form only, and has given the contractor the master key after all. - Performance isn't free. JIT or AOT compilation of WASM is good; it is not native.
- The ecosystem is young. Library support for capability-style APIs lags behind the languages compiling to WASM.
- It won't replace containers, whatever the marketing suggests. It's a different granularity, and it earns its place where you want many small isolated units that start fast.
WASM can put the centre back in through the component registry, which is being decided right now while everybody argues about the specification.
The component model's promise is that you assemble software out of parts that need not share a language. That promise requires a place to find the parts. We have watched this film: the default public registry becomes the namespace, the namespace becomes the ecosystem, and whoever runs it ends up holding the decision about what exists. npm, Docker Hub, the app stores. In every case the technical artefact was open and the discovery layer was not, and the discovery layer is where the power turned out to be. A rate limit on pulls is a tax on every build in the industry, imposed by a company nobody elected.
The specific risk for WASI is sharper than for containers, because components are meant to be small and numerous. An application might pull two hundred of them. Two hundred dependencies resolved through one index, each one running with whatever authority the host grants it, is a supply chain with a single curator and a very large blast radius. Note also that a capability system makes the authority auditable without making the code trustworthy: a module confined to one directory can still have been replaced with a version that leaks what is in that directory.
Where is the open version? Ahead, for once, and that is worth defending. The component model is specified in the open, the runtimes are open source, and registry work is happening in standards bodies rather than in one company's product. Running your own registry is currently a normal thing to do rather than an act of defiance. That window closes the moment one index becomes the default in the tooling, because defaults are destiny.
The rule is simple: if you cannot rebuild your artefacts from source you control, and mirror them somewhere you own, then the registry is part of your infrastructure and somebody else is running it. Pin your components, mirror them and treat a dependency you can only fetch from one host as an outage you have scheduled for a date of their choosing.