Feature

Approve Plugin Access Only When the Job Justifies It

Check EmDash capability scope, allowed hosts, sandbox setup and update consent before approving plugins that can edit, publish or transmit site content.

Impetuous · · 4 Min Read

Approve EmDash plugin permissions only when the requested capabilities, external destinations and execution mode fit the plugin’s job. A plugin with content:write can edit any content—not just articles it created. The sandbox restricts available operations; it does not make every permitted operation safe. EmDash’s capability documentation explicitly describes these grants as coarse.

Select the execution mode, most sensitive grant and network scope to see what needs review.

Permission Review Gate

Review Read Scope Before Approval

A confirmed runner supplies sandbox isolation; it does not make permitted operations safe.

Content read exposes site content. Confirm that editorial content, rather than public URLs alone, is needed.

No network grant means no ctx.http. Review the full manifest for other requested authority.

Review cue, not a security certification. Choose the highest-impact grant here, then review every grant in the manifest.

Grant and Runtime Caveats
  • content:write can create, update and delete any content; it implies read access.
  • content:publish controls publish, unpublish, schedule and unschedule actions; it implies read access but is separate from editing.
  • Retained revisions can include field values removed from current content.
  • Media metadata access, file-byte access and metadata editing do not imply one another.
  • A leading *. host pattern includes the named domain and its subdomains. Unrestricted network permission skips the manifest allowlist.
  • Native plugins have direct process access. Moving a plugin to the native list does not repair a missing sandbox runner.

Source: EmDash capabilities, installation modes and sandbox setup. With JavaScript disabled, the result describes the initial selections only.

Capability Grants Apply Across the Site

Sandboxed plugins start with access to their own declared storage and KV collections. Additional host-provided APIs are gated by capabilities declared in emdash-plugin.jsonc. Without content:read or a capability that implies it, a plugin does not receive ctx.content; without network permission, it does not receive ctx.http. With an active runner, direct network primitives are blocked and requests must pass through the bridge.

These are the grants most likely to affect a content website:

Capability Permitted Operations Approval Test
content:read Read site content Needs editorial content, not just public URLs?
content:write Create, update and delete content; implies read Needs site-wide editing authority?
content:publish Publish, unpublish, schedule and unschedule; implies read Should control publication state?
content:revisions:read Read retained revisions; implies read Needs access to historical field values?
media:metadata:write Change alt text, captions and focal points Is metadata editing sufficient?
network:request Send requests to declared allowed hosts Are the destination and payload justified?

Content editing and publication actions have separate grants. Media metadata access, file-byte access and metadata editing do not imply one another. Retained revisions can include field values an administrator later removed. These distinctions are documented in the full capability reference.

For example, an alt-text assistant that processes uploaded images might justify media:read, media:bytes:read, media:metadata:write and access to a specific external API. That task alone does not justify content deletion, user-account access or publication authority. This is a proposed approval boundary, not a claim about an existing plugin’s manifest.

Network Grants Control Destinations, Not Payloads

For fixed API destinations, prefer network:request with explicit allowedHosts. A leading *. matches both the named domain and its subdomains, so a wildcard grants more reach than one exact host.

network:request:unrestricted skips that manifest allowlist. It is intended for operator-configured destinations, such as a webhook URL entered at runtime. The bridge still restricts protocols to HTTP and HTTPS, blocks known internal hosts and private literal addresses, and rechecks redirects. Those protections do not turn unrestricted access into a narrow destination grant. Network host rules

Review read access and network access together. A plugin permitted to read content and contact an approved service can transmit content there. An allowlist controls where requests go, not whether their payloads are appropriate for that service. Approval therefore needs a reason for both the destination and the data being sent.

Native Execution Is Not Sandbox Isolation

A capability declaration is not a substitute for runtime isolation. With sandboxing enabled, registry installs and npm plugins under sandboxed: [] use the configured sandbox runner. Native plugins under plugins: [] run in the EmDash server process without sandbox isolation; they have declared plugin APIs plus direct process access. Installation modes

On Cloudflare, sandboxing requires the Workers Paid plan, a Worker Loader binding named LOADER, and a PluginBridge export. On Node.js, it requires the sandbox runner and its workerd dependency. A missing runner can produce SANDBOX_NOT_AVAILABLE. Moving the plugin into the native list changes the trust model rather than fixing isolation. Sandbox setup

Resource protection also differs by runner:

Limit Per Invocation Cloudflare Node.js
CPU time 50 ms Not enforced
Subrequests 10 Not enforced
Wall time 30 seconds Enforced; duration not stated here
Separate per-plugin memory Not enforced Not enforced

Keep Node’s sandbox: false debugging option out of production: it removes isolation and limits. These limits and debugging behavior are described in the sandbox documentation. Cloudflare’s CPU and subrequest protections should not be assumed to apply to Node.js.

Approval Records Must Cover Behavior and Execution

Define the Job Before Reviewing Grants

Record what the plugin must read, change and transmit. Compare each requested grant with that job. For a metadata-only workflow, broader content authority needs a separate justification; for a publishing workflow, distinguish editing from publication-state control.

In the admin’s Registry page, inspect the publisher, verification status and requested permissions. EmDash verifies signed release records and the downloaded bundle. That establishes integrity, not that the plugin’s behavior deserves every requested grant. Registry verification

Test With Isolated Data and Coordinate Writes

Use representative non-production content and controlled external destinations. Test intended behavior and operations the plugin should be denied. A preview URL alone is not resource isolation; see which Worker Preview bindings still reach production.

Plugin updates and deletes are programmatic writes: an editor’s advisory entry lock does not block them. Establish when automation may modify shared entries rather than assuming an open editing session prevents changes. Programmatic write behavior

Review Updates Even Without New Permissions

Registry updates require fresh confirmation when they add permissions or MCP tools, or change a route from authenticated to public. The installed version remains until approval.

For npm-managed plugins, review access changes before updating the dependency and deploying; those updates happen outside the admin panel. Review release behavior too: an update can misuse authority it already has without requesting a new capability. Update consent and npm installation

Keep an approval record with the release version, execution mode, grants, allowed hosts, reviewer and test result. The record should explain why the plugin needs the access and how it was tested—not merely show that someone clicked Install.