mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

Security

EmDash's Sandboxed Plugin Registry: How Cloudflare Built Agent-Friendly CMS Extensions

Cloudflare's EmDash 1.0 uses sandboxed plugins and decentralized registries to let AI agents extend CMS workflows without breaking security boundaries.

Source: blog.cloudflare.com
EmDash's Sandboxed Plugin Registry: How Cloudflare Built Agent-Friendly CMS Extensions

Cloudflare just shipped EmDash 1.0, a CMS built for Astro that treats plugin security as a first-class concern. The interesting part is not the CMS itself but the plugin architecture: sandboxed extensions, a decentralized registry, and explicit support for agent-driven workflows. As coding agents increasingly interact with content platforms to generate and publish material, the plugin boundary becomes a critical security surface. EmDash’s approach offers a practical model for how infrastructure can support agentic automation without creating supply-chain vulnerabilities.

The Plugin Problem for Agent Workflows

Traditional CMS plugin ecosystems (WordPress, Drupal, Ghost) assume human operators who manually vet extensions before installation. An agent-driven workflow breaks that assumption. When an AI agent needs to extend a CMS to support a new content type or integrate a third-party API, it cannot pause for human review. It needs structured, verifiable plugin interfaces that enforce isolation by default.

EmDash addresses this by treating plugins as untrusted code from the start. The sandbox enforces boundaries between plugin execution and core CMS state. The decentralized registry shifts trust verification from a central authority to cryptographic signatures and publisher-controlled allowlists.

Sandbox Architecture

EmDash’s plugin sandbox relies on Cloudflare Workers’ V8 isolate model. Each plugin runs in its own isolate with no shared memory, no access to the filesystem, and no direct network calls. The plugin receives a capability token that grants access to specific CMS APIs (content CRUD, asset upload, schema modification) but nothing else.

Key isolation primitives:

  • V8 isolates: Separate JavaScript heaps per plugin, enforced by the Workers runtime
  • Capability tokens: Scoped to specific resources (e.g., “write to /blog/posts” but not “/admin/users”)
  • No ambient authority: Plugins cannot discover or access APIs they were not explicitly granted
  • Execution time limits: 50ms CPU time per request, 128MB memory ceiling

This model prevents a malicious plugin from exfiltrating publisher credentials, modifying unrelated content, or accessing other plugins’ state. The trade-off is that plugins cannot perform long-running tasks or maintain persistent connections. For agent workflows, this is acceptable because agents typically orchestrate short, stateless operations (generate content, validate schema, trigger build).

Decentralized Registry Model

EmDash’s registry is not a centralized npm-style repository. Instead, it is a collection of signed manifests hosted on IPFS and indexed by a Cloudflare-operated discovery service. Publishers verify plugin integrity using Ed25519 signatures and can maintain private allowlists.

How it works:

  1. Plugin author publishes a manifest (JSON file with code hash, permissions, signature) to IPFS
  2. Author submits the IPFS CID to the discovery service (optional, for public visibility)
  3. Publisher fetches the manifest, verifies the signature against a known public key
  4. Publisher adds the plugin to their local allowlist if verification passes
  5. EmDash downloads the plugin code (also from IPFS) and validates the hash before execution

This architecture prevents the registry itself from becoming a trust bottleneck. Even if the discovery service is compromised, it cannot inject malicious code because publishers verify signatures independently. The downside is operational complexity: publishers must manage public keys and allowlists, which is not trivial for non-technical users.

Agent-Friendly API Design

EmDash exposes a structured tool interface designed for autonomous agents. Unlike traditional CMS REST APIs that return HTML or require session cookies, EmDash’s agent API uses JSON-RPC over HTTP with bearer tokens.

Agent-specific features:

  • Structured tool definitions: Each plugin declares its capabilities in a machine-readable schema (similar to OpenAPI but optimized for LLM function calling)
  • Idempotent operations: All write operations accept an idempotency key to prevent duplicate content creation
  • Audit logs: Every agent action is logged with the agent’s identity, tool call parameters, and result
  • Rate limits: Per-agent quotas (100 requests/minute by default) to prevent runaway loops

Example tool definition for a content generation plugin:

{
  "name": "generate_blog_post",
  "description": "Generate a blog post from a topic and outline",
  "parameters": {
    "topic": { "type": "string", "required": true },
    "outline": { "type": "array", "items": { "type": "string" } },
    "tone": { "type": "string", "enum": ["technical", "casual", "formal"] }
  },
  "permissions": ["content:write:blog"],
  "idempotent": true
}

An agent can discover available tools by querying the /tools endpoint, then invoke them using the JSON-RPC protocol. The CMS validates the agent’s bearer token, checks the requested permissions against the token’s scope, and executes the tool in the appropriate sandbox.

Deployment Shape

EmDash runs entirely on Cloudflare’s edge infrastructure. The CMS core is a Workers script, content is stored in Durable Objects, and static assets are served from R2. Plugins are also Workers scripts, deployed to the same edge network but isolated in separate V8 contexts.

Component breakdown:

ComponentRuntimeStateNetwork Boundary
CMS CoreWorkers (V8)Durable ObjectsPublic HTTP + internal RPC
Plugin SandboxWorkers (V8)Ephemeral onlyNo direct network access
Content StoreDurable ObjectsTransactional SQLInternal RPC only
Asset CDNR2 + CacheImmutable blobsPublic HTTP (read-only)
Registry IndexWorkers KVSigned manifestsPublic HTTP (read-only)

This architecture means plugins execute at the edge, close to the end user, with sub-10ms latency for most operations. The trade-off is that plugins cannot use traditional server-side libraries (no Node.js modules, no native bindings). Authors must write plugins in vanilla JavaScript or use Workers-compatible libraries.

Failure Modes

Plugin crashes: If a plugin throws an uncaught exception, the sandbox terminates and returns an error to the caller. The CMS core remains unaffected. Agents should implement retry logic with exponential backoff.

Registry unavailability: If IPFS is unreachable, publishers cannot install new plugins but existing plugins continue to work (code is cached in R2). The discovery service is optional, so private registries can operate independently.

Token compromise: If an agent’s bearer token is leaked, an attacker can perform any operation the token allows. EmDash mitigates this by requiring short-lived tokens (1-hour expiry by default) and supporting token revocation via the /auth/revoke endpoint.

Quota exhaustion: If an agent exceeds its rate limit, subsequent requests return HTTP 429. The agent must back off or request a quota increase from the publisher. There is no automatic quota scaling to prevent runaway costs.

Observability

EmDash logs every plugin invocation to Cloudflare Logpush. Each log entry includes:

  • Plugin identifier (IPFS CID + version)
  • Agent identity (bearer token subject)
  • Tool name and parameters
  • Execution time and memory usage
  • Success/failure status
  • Capability token scope

Publishers can stream logs to their own observability stack (Datadog, Grafana, Splunk) or query them directly using Cloudflare’s analytics API. For agent workflows, this is critical for debugging unexpected behavior and auditing compliance with content policies.

Technical Verdict

Use EmDash’s plugin model when:

  • You need to let AI agents extend a CMS without manual review
  • You want cryptographic verification of plugin integrity
  • You can tolerate the operational overhead of managing public keys and allowlists
  • Your plugins fit within the Workers execution model (short-lived, stateless, no native code)

Avoid it when:

  • Your plugins require long-running tasks (video transcoding, ML inference)
  • You need a centralized plugin marketplace with automatic updates
  • Your users are non-technical and cannot manage cryptographic keys
  • You need compatibility with existing CMS ecosystems (WordPress plugins, Drupal modules)

The sandbox and registry architecture is sound for agent-driven workflows, but the deployment model locks you into Cloudflare’s edge platform. If you need portability or hybrid cloud deployment, you will need to reimplement the isolation primitives on a different runtime.