Most CMS security reviews end up being plugin reviews. EmDash, the open-source TypeScript CMS for Astro, was designed around that fact: its main architectural bet is that plugins should not be trusted with the whole site. Here is how the sandbox works, where it stops, and how we treat it in enterprise reviews at Seahawk and Seahawk VIP.
The problem it is solving
In a traditional CMS, a plugin runs in the same process as everything else. It can read the database, the environment and the filesystem, and it can make any network call it likes. A single vulnerable or malicious plugin is a whole-site compromise. Patchstack’s research found that 96% of the WordPress vulnerabilities it uncovered in 2024 were in plugins, which is why plugin governance dominates WordPress security programs.
How the EmDash sandbox works
Capabilities are declared up front. Every sandboxed plugin ships a manifest listing what it needs, for example:
content:read,content:writeorcontent:publishmedia:writecomments:moderateredirects:writeortaxonomies:writenetwork:request, restricted to a named list of allowed hosts
An administrator sees the list at install time and approves it, much like app permissions on a phone. A plugin that asks for network:request to hooks.slack.com can call Slack and nothing else.
Plugins run in isolation. On Cloudflare, each plugin runs in its own Dynamic Worker, a V8 isolate created on demand. On Node.js, each runs inside workerd, Cloudflare’s open-source Workers runtime, in a separate child process. Either way the plugin has no access to environment variables, the filesystem, other plugins’ storage or undeclared hosts. It talks to EmDash only through the APIs its capabilities allow.
Resources are bounded. On Cloudflare, each invocation is capped at 50 ms of CPU, 10 subrequests, 128 MB of memory and 30 seconds of wall time. On Node.js only the wall-time limit is enforced today.
Where the sandbox stops
Treat these as review items, not footnotes.
- Native plugins are not sandboxed. Plugins that need custom React admin screens or Astro components run in the server process with full access. Review them like any other code you deploy.
- The strongest isolation is on Cloudflare. On Cloudflare, sandboxing needs the Workers Paid plan and a Worker Loader binding. The starter templates deploy with sandboxing off on the free plan, so check it is actually on. On Node.js you get process isolation but looser resource limits.
- Some deployments cannot sandbox. Sandboxed plugins are not available on Hyperdrive deployments, and registry installs fail without a configured sandbox runner.
- Permissions are only as good as the approver. A plugin granted
content:publishcan publish. The model narrows the blast radius; it does not replace judgment. - The registry is young. Plugins are published to an open, AT Protocol-based registry, with releases signed by their publishers and a moderation labeler run by Cloudflare. It has not been tested at the scale of the WordPress directory yet.
AI agents get the same treatment
Every EmDash site includes an MCP server so tools like Claude, Codex and Cursor can work with content. Access needs a bearer token (OAuth 2.1 with PKCE, a personal access token or a device login), and token scopes are checked against the user’s role. An agent acting for an Author cannot do what an Editor can. For teams bringing AI into publishing, this is a cleaner story than handing an agent an admin password.
How we review an EmDash deployment
- Confirm the runtime. Cloudflare with the Worker Loader binding, or Node.js with the workerd runner. Verify sandboxing is enabled, not assumed.
- List every plugin by type. Sandboxed plugins get a permission review; native plugins get a code review.
- Apply least privilege. Reject any
network:requestwithout a tight host list, and question every publish or write capability. - Scope agent access. Issue MCP tokens per agent and per role. Never share an admin token.
- Lock down sign-in. EmDash defaults to passkeys, with OAuth, magic links, Cloudflare Access and Microsoft Entra available. Enforce SSO where policy requires it.
- Keep the usual controls. Dependency updates, backups, monitoring and a WAF still matter. The sandbox covers plugins, not the rest of the stack.
How it compares
WordPress at enterprise scale manages plugin risk with process: curated allow-lists, code review, platforms like WordPress VIP that vet what can be deployed, and continuous patching. That works, and it is how we run large WordPress fleets. EmDash moves part of that control into the runtime. Neither removes the need for review; EmDash makes the default safer when a plugin is wrong.
Next step
If your team is evaluating EmDash, talk to Seahawk about a build or a pilot with a security review baked in. If you are staying on WordPress at scale, Seahawk VIP runs enterprise WordPress with the same discipline.