Skip to content

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.

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 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:

Terminal window
cat /github/acme/api/_issues/_open/2853/title

the sequence is:

  1. The FUSE mount receives a read() on the path.
  2. The host runtime resolves it: provider is github, path segments identify owner acme, repo api, collection _issues, filter _open, issue 2853, field title.
  3. The host checks its capacity-bounded cache. On a miss, it asks the provider to answer a read-file call.
  4. The provider returns a query descriptor: “make a GET to api.github.com/repos/acme/api/issues/2853, extract the title field.”
  5. The host makes that request, attaches Authorization: Bearer <token>, and caches the result.
  6. 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.

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.

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.

The host runtime is the trust boundary:

ResourceOwned by
Credentials and tokensHost
Network socketsHost
CacheHost
Inode tableHost
HTTPS callout executionHost
Path resolution logicHost
Three read ops (lookup-child, list-children, read-file)Provider
External API query descriptorsProvider

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.

  • 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-wasip2 sandbox 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.