Capabilities and security
omnifs is built on one rule: a provider gets exactly what it asked for, nothing more. That rule has two enforcement layers: the capability system, which controls what external callouts a provider can make; and the wasmtime sandbox, which limits what a misbehaving component can touch on your machine.
No ambient authority
Section titled “No ambient authority”When a provider is loaded, it ships a manifest of the resources it needs. Two kinds of declarations are currently recognized:
- HTTPS hosts. The specific hostnames the provider is allowed to contact (for example,
api.github.com). - Secret names. Named credentials the host should inject into callouts on the provider’s behalf (for example,
GITHUB_TOKEN).
The host reads this manifest at load time. If a provider later attempts to reach a host or secret it did not declare, the request is denied. There is no fallback, no warning-and-continue, no capability that is silently trusted because the provider “looks safe.”
The github provider, concretely
Section titled “The github provider, concretely”The github provider declares one HTTPS host (api.github.com, or the api_url you configure for GitHub Enterprise) and one secret (GITHUB_TOKEN). Those are the only two capabilities it is granted.
When you run:
cat /github/acme/api/_issues/_open/2853/titlethe sequence is:
- The FUSE mount receives a
read()on the path. - The host runtime resolves it: provider is
github, path segments identify owneracme, repoapi, collection_issues, filter_open, issue2853, fieldtitle. - The host checks its capacity-bounded cache. On a miss, it asks the provider to answer a
read-filecall. - The provider returns a query descriptor: “make a GET to
api.github.com/repos/acme/api/issues/2853, extract the title field.” - The host makes that request, attaches
Authorization: Bearer <token>, and caches the result. - Bytes flow back to the calling process.
The provider participated in steps 3 and 4. It never touched the network. It never saw the token.
wasm32-wasip2 sandboxing
Section titled “wasm32-wasip2 sandboxing”Every provider compiles to a wasm32-wasip2 component and runs under wasmtime. The sandbox enforces:
- No filesystem access. A provider cannot read or write paths on your local disk.
- No network access. A provider cannot open a socket or make an HTTP request directly.
- No cross-provider visibility. One provider cannot read another provider’s state.
- Fault containment. A panic, out-of-memory error, or infinite loop inside a provider terminates that component instance. It cannot propagate to the host process, to other providers, or to any other mounted path.
The only surface a provider exposes to the host is three operations, hyphenated to match the omnifs:provider@1.0.0 WIT interface:
package omnifs:provider@1.0.0;
interface provider { lookup-child: func(parent: path, name: string) -> option<node>; list-children: func(parent: path) -> list<node>; read-file: func(path: path) -> result<bytes, error>;}That is the complete boundary. The host calls in; nothing else flows the other direction.
Undeclared reach is denied
Section titled “Undeclared reach is denied”The design is fail-closed. If a provider omits a hostname from its manifest and later attempts to use it, the callout never happens. If a provider attempts to read a secret it did not declare, the host does not supply it.
This matters for community-sourced providers: you can load a third-party .wasm component from a registry without auditing its network behavior in advance. The worst it can do is fail to answer read-file calls, which surfaces as an empty file or a read error. It cannot exfiltrate credentials, reach services it was not granted, or affect paths owned by another provider.
What the host owns
Section titled “What the host owns”The host runtime is the trust boundary:
| Resource | Owned by |
|---|---|
| Credentials and tokens | Host |
| Network sockets | Host |
| Cache | Host |
| Inode table | Host |
| HTTPS callout execution | Host |
| Path resolution logic | Host |
Three read ops (lookup-child, list-children, read-file) | Provider |
| External API query descriptors | Provider |
A provider author cannot expand this table unilaterally. Adding a capability requires declaring it in the manifest, which the operator grants explicitly when loading the provider.
Summary
Section titled “Summary”- The host holds all credentials; providers never see them.
- Providers declare the HTTPS hosts and secrets they need; undeclared reach is denied.
- Each provider runs in a
wasm32-wasip2sandbox under wasmtime: no disk, no network, no cross-provider access, fault contained. - The wire boundary is exactly three operations:
lookup-child,list-children,read-file. - A third-party provider can be loaded without auditing its network behavior because the capability system makes that behavior structurally impossible to exceed.