Skip to main content

Capability Manifest

A capability manifest is a fully-resolved, portable JSON document describing what a nono sandbox enforces. It is the machine-consumable contract for sandbox configuration.

Profiles vs Manifests

Profiles compile down to manifests. A manifest is what a fully-resolved profile looks like once all inheritance, group expansion, and patching is applied.

Schema

The manifest schema is at crates/nono/schema/capability-manifest.schema.json, using JSON Schema Draft 2020-12.

Capability Domains

The schema defines four capability domains, modeled after WASI’s capability-based security model:

Filesystem

Controls which paths the sandboxed process can access and at what level.
  • grants: Each grant specifies a path, an access mode (read, write, or readwrite), and an optional type (file or directory, defaults to directory).
  • deny: Paths to explicitly deny. On macOS/Seatbelt, deny rules take precedence over grants. On Linux/Landlock, deny is expressed by omitting grants.
  • Paths are unresolved strings (may use ~). Canonicalization happens at enforcement time, keeping manifests portable across machines.

Network

Controls outbound connectivity, domain filtering, L7 endpoint restrictions, and port allowlists.
  • mode: blocked (no network), proxy (routed through nono proxy for filtering/credential injection), or unrestricted (default).
  • endpoints: Per-host L7 method+path filtering. When rules is non-empty, only matching requests are allowed (default-deny). When absent, all paths on that host are permitted.
  • ports: Fine-grained TCP port control for connect (outbound), bind (listening), and localhost (bidirectional IPC).

Credentials

Configures credential routes for the reverse proxy. The sandboxed process never sees the actual credentials.
  • source: URI for the credential. Supported schemes: env:// (environment variable), file:// (file contents), op:// (1Password), apple-password:// (macOS Keychain), or a bare account name for the system keystore.
  • inject: How the credential is inserted into outbound requests. Modes: header (default), url_path, query_param, basic_auth.
  • endpoint_rules: Optional L7 filtering per credential route (default-deny when non-empty).

Process

Controls process-level isolation and execution strategy.
  • signal_mode: isolated (default), allow_same_sandbox, or allow_all.
  • ipc_mode: shared_memory_only (default) or full (needed for Python multiprocessing).
  • exec_strategy: direct (exec, nono disappears), monitor (sandbox-then-fork, default), or supervised (fork-then-sandbox, supports rollback).

Rollback

Design Principles

  1. Fully resolved — No inheritance, no extends, no group references. What you see is what the sandbox enforces.
  2. No legacy aliases — Clean field names only. Legacy compatibility is the profile layer’s concern.
  3. No hooks — Hooks are CLI UX, not sandbox enforcement. They belong in profiles.
  4. Portable paths — Paths are unresolved strings. Canonicalization happens at enforcement time.
  5. Schema-first — The JSON Schema is the source of truth. Rust types are generated from it (via typify), not the other way around.
  6. Versioned — The version field (semver) tells consumers which schema fields are available.

Full Example