Skip to content

Build2 publishers3 min readPublished

EmDash 1.0 moves plugin vetting from manual review to a site owner's signed allowlist

Cloudflare's EmDash 1.0 runs each CMS plugin in its own isolate capped at 50ms of CPU per request, a dev.to breakdown says. Isolation limits what a bad plugin can reach, and choosing which publisher keys to trust stays with the site owner.

The Engineer · Build desk

Illustration accompanying EmDash 1.0 moves plugin vetting from manual review to a site owner's signed allowlist

What happened

  • Cloudflare released EmDash 1.0 as a stable, free Astro-based CMS under the MIT license, after introducing it on April 1 and working on it for five months with contributors and production users.
  • Alongside it, Cloudflare launched a decentralized plugin registry that lets developers publish without handing ownership of their identity or releases to a central marketplace.
  • Cloudflare moved its own blog to EmDash in August, planning for millions of pageviews a week and legitimate traffic spikes of up to 5,000 requests per second.
  • Avulux, worn down by WordPress maintenance, converted a custom microsite to EmDash in under a day using EmDash Agent Skills, Cloudflare said.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint Integrations that need long-running work or their own network connections do not fit a 50ms isolate without direct network access, so those plugins need a different design before they can run.
  • decision Each site owner now decides which publisher keys to trust, a job the write-up itself expects non-technical users to find hard.
  • exposure A plugin can still write bad content into the paths it was granted; the sandbox walls off credentials, other plugins and unrelated content only.

Each EmDash plugin runs in its own V8 isolate on the Workers runtime, with no shared memory, no filesystem access and no direct network calls, according to a dev.to write-up of the release [4]. What the plugin gets is a capability token scoped to named CMS APIs and paths, such as "write to /blog/posts" but not "/admin/users" [5]. It cannot discover an API it was not granted [5]. Each request is capped at 50ms of CPU time and 128MB of memory [6]. Those figures come from the write-up, and anyone sizing a plugin against them is relying on one author [6].

The author names the cost. Plugins cannot run long tasks or hold persistent connections [7]. The write-up calls that acceptable because agents mostly orchestrate short, stateless steps, such as generating a post or triggering a build [7]. That holds only where every plugin call finishes its compute inside 50ms and keeps nothing open between requests [6]. The case to test first is one the author raises: an agent extending the CMS to integrate a third-party API [12]. With no direct network calls, that plugin needs the CMS to make the request through a granted capability, and the write-up does not describe one [4].

The registry is a set of signed manifests hosted on IPFS and indexed by a Cloudflare-operated discovery service, according to the same write-up [8]. Installation runs in order [9]:

1. The author publishes a manifest with the code hash, the plugin's permissions and an Ed25519 signature to IPFS, and can submit its CID to the discovery service for public listing [8][9]. 2. The site owner fetches the manifest and checks the signature against a public key they already know [9]. 3. If it verifies, the plugin goes on the site's local allowlist [9]. 4. EmDash downloads the code from IPFS and checks it against the hash before running it [9].

This is careful engineering. Because each site checks signatures itself, a compromised discovery service cannot inject code [10]. The same design puts the vetting in step 2. A valid signature proves which key signed a manifest. Whether that key belongs to someone whose code should run on the site is still a judgement, made by the site owner when the key goes on the allowlist [9]. The write-up calls managing those keys and allowlists "not trivial for non-technical users" [11]. Greg Barbosa, director of innovation and systems at Avulux, said of his company's move: "With EmDash, we now have a shared platform that developers can extend and marketers can edit content." [18]

The write-up's premise is that an agent extending a CMS cannot pause for human review, the step older plugin ecosystems assumed [12]. After installation, isolation limits the damage. The author says the model stops a malicious plugin from exfiltrating publisher credentials, modifying unrelated content or reading other plugins' state [13]. A plugin holding write access to /blog/posts can still write whatever it wants to /blog/posts [5][13]. Inside that scope, the agent API logs each action with the agent's identity, parameters and result, and sets a default quota of 100 requests a minute per agent [14]. At that default, a looping agent can still send 6,000 requests an hour [1].

In my view, isolation by default is the right design for a CMS that agents extend, provided plugins stay inside short, stateless jobs [7]. Under the flow as described, a plugin an agent wants to install runs only after its publisher's key passes the site's allowlist check [9].

What to watch

  • Whether Cloudflare's own EmDash documentation confirms the 50ms CPU cap, the 128MB ceiling and the Ed25519 manifest format described in the dev.to write-up.
  • Whether EmDash lets an agent add a publisher key to a site's allowlist without a person approving it.
  • How a plugin that integrates a third-party API gets network access when its isolate cannot make direct calls.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories