Skip to content

CONCEPT Cited by 2 sources

Capability manifest

Definition

A capability manifest is an upfront, declarative, install-time-inspectable statement of the capabilities a piece of third-party code (plugin, agent tool, LLM-generated extension, untrusted script) requires to function. The runtime enforces that the code cannot exceed the manifest; the user / administrator makes the install decision based on the manifest alone, without reading the implementation.

The analogy made explicit in Cloudflare's EmDash launch post is the OAuth scope grant flow:

"similar to going through an OAuth flow and granting a 3rd party app a specific set of scoped permissions."

The decision surface is the scope list, not the application binary.

Required properties

  • Declarative, not imperative. The manifest describes needed capabilities; it does not invoke them. Capability use happens at runtime against bindings/APIs that only function for declared capabilities.
  • Install-time inspectable. The manifest is visible before the code runs — ideally before it's installed. The user can refuse based on what's requested.
  • Runtime-enforced. A capability not declared is not available: calls to external resources, APIs, or hooks that the plugin didn't declare must fail at the runtime boundary, not at a policy layer on top.
  • Granular. Grants are per-resource, not per-category. "Network" is too coarse; "network access to api.github.com" is the shape.
  • Versioned. As the platform evolves, the capability lexicon grows; the manifest format must support versioning so older plugins don't break silently or newer plugins can't declare ambiguous capabilities.

Canonical examples on this wiki

EmDash plugin manifest

definePlugin({
  id: "notify-on-publish",
  version: "1.0.0",
  capabilities: ["read:content", "email:send"],
  hooks: {
    "content:afterSave": async (event, ctx) => { /* ... */ }
  },
});

Two capabilities (read:content, email:send), one hook (content:afterSave). No filesystem, no arbitrary network. If network is needed, the manifest specifies the exact hostname. See systems/emdash + patterns/capability-manifest-plugin-isolation.

Project Think self-authored-extension manifest

{
  "name": "github",
  "permissions": {
    "network": ["api.github.com"],
    "workspace": "read-write"
  }
}

An agent-authored extension for a Dynamic Worker; same declarative-then-enforce shape at a different use-case. See systems/project-think + concepts/capability-based-sandbox.

Why this matters

Without a capability manifest, the user has only two options for a third-party plugin: (a) trust the plugin blindly, (b) audit its source code. The first scales but is insecure; the second is secure but doesn't scale.

A capability manifest gives the user a third option: inspect the manifest, understand what permissions are being granted, and refuse if the request is too broad — without reading the source. This is what makes third-party plugin ecosystems viable at scale without an expensive marketplace-vetting apparatus (see concepts/plugin-marketplace-lock-in).

Relationship to capability-based sandbox

The capability-based sandbox is the runtime enforcement mechanism; the capability manifest is the declarative interface to it. The sandbox says "start with nothing, grant only what's named"; the manifest says "here's what to name."

Both are needed:

  • Manifest without sandbox: the declarations are advisory; the code can still do whatever the host platform gives it. WordPress plugin headers are ≈ this.
  • Sandbox without manifest: the user has no install-time visibility into what the plugin will try to do; grants become ad hoc or all-or-nothing.
  • Sandbox + manifest: the user decides up-front what the plugin is permitted to do, and the runtime enforces that decision at every invocation.

Failure modes to watch

  • Manifest capabilities too coarse. If email:send actually means "arbitrary email to arbitrary recipients", the manifest is theatre. Capabilities must be as narrow as the target API warrants.
  • Capabilities evolve without SemVer. A platform adding a new capability to an existing scope (email:send now also lets you read inbox) silently grants broader access than the install-time inspection showed.
  • Opaque capability names. Names like admin, power-user, advanced hide what's actually granted. Each name needs a clear, inspectable definition.
  • Capability exfiltration via composition. Two individually-narrow capabilities can combine into a broader one (read:content + network to an attacker- controlled hostname = content exfiltration). The manifest must make composition risks legible.

Seen in

Last updated · 200 distilled / 1,178 read