{"id":97994,"date":"2026-10-03T10:14:00","date_gmt":"2026-10-03T14:14:00","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=97994"},"modified":"2026-09-29T07:49:18","modified_gmt":"2026-09-29T11:49:18","slug":"emdash-plugin-permissions-user-trust-97994","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/emdash-plugin-permissions-user-trust-97994\/","title":{"rendered":"EmDash Plugin Permissions: The Real Danger Isn&#8217;t What You Think"},"content":{"rendered":"<p>The most dangerous plugin in EmDash isn&#8217;t the one that secretly steals your data. It&#8217;s the one that asks for everything and gets approved. Cloudflare&#8217;s new CMS has a sandbox that physically blocks unauthorized access, but it cannot stop you from granting permission to a plugin that requests too many capabilities. That&#8217;s not a technical flaw. It&#8217;s a trust problem wearing a security badge.<\/p>\n<h2>How EmDash Plugin Permissions Actually Work<\/h2>\n<p>EmDash runs every plugin inside its own V8 isolate, a lightweight sandbox powered by Cloudflare&#8217;s dynamic workers. The plugin cannot touch your database, your file system, or any other part of the CMS unless you explicitly allow it.<\/p>\n<p>Each plugin declares its capabilities in a manifest. A contact form plugin might request <code>read content<\/code>codecodecodecode and <code>send email<\/code>codecodecodecode. That&#8217;s it. The runtime enforces the boundary at the hardware level using Linux namespaces, seccomp filters, and memory protection keys.<\/p>\n<p>But here&#8217;s the thing: EmDash does not limit how many capabilities a single plugin can request. A plugin could ask for <code>read content<\/code>codecodecodecode, <code>write content<\/code>codecodecodecode, <code>delete content<\/code>codecodecodecode, <code>read users<\/code>codecodecodecode, <code>write users<\/code>codecodecodecode, <code>send email<\/code>codecodecodecode, <code>make external network requests<\/code>codecodecodecode, and <code>manage settings<\/code>codecodecodecode. The system will happily let it declare all of those. The question is whether you, the site owner, will approve them.<\/p>\n<h2>The Manifest System: What Plugins Can and Cannot Declare<\/h2>\n<p>The manifest is a simple JSON-like structure inside the plugin code. Here&#8217;s a real example from the <a href=\"https:\/\/developers.cloudflare.com\/emdash\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">EmDash documentation<\/a>:<\/p>\n<p>&#8220;`javascript<\/p>\n<p>definePlugin({<\/p>\n<p>  id: &#8216;my-plugin&#8217;,<\/p>\n<p>  version: &#8216;1.0.0&#8217;,<\/p>\n<p>  capabilities: [&#8216;read:content&#8217;, &#8217;email:send&#8217;],<\/p>\n<p>  hooks: {<\/p>\n<p>    &#8216;post:published&#8217;: async (context) =&gt; {<\/p>\n<p>      const email = context.getCapability(&#8217;email:send&#8217;);<\/p>\n<p>      \/\/ send email about new post<\/p>\n<p>    }<\/p>\n<p>  }<\/p>\n<p>})<\/p>\n<p>&#8220;`<\/p>\n<p>The plugin cannot access anything outside those declared capabilities. It cannot read user passwords, cannot write to the database, cannot make HTTP requests to external servers. The dynamic worker enforces this at runtime.<\/p>\n<p>But notice: nothing prevents the plugin from listing <code>read:users<\/code>codecodecodecode, <code>write:content<\/code>codecodecodecode, <code>network:all<\/code>codecodecodecode, and <code>admin:settings<\/code>codecodecodecode. The system does not have a &#8220;max permissions&#8221; cap. It trusts you to evaluate each request.<\/p>\n<h2>The Real &#8220;Flaw&#8221;: User Trust vs. Technical Enforcement<\/h2>\n<p>The WordPress ecosystem conditioned millions of users to install plugins without reading what they do. You click &#8220;Install Now&#8221; and the plugin gets full access to everything. EmDash breaks that pattern. You see a permission dialog before installation.<\/p>\n<p>But will you actually read it? History says no. The same users who clicked &#8220;I agree&#8221; without reading terms of service will click &#8220;Approve&#8221; on a plugin that requests <code>delete:all<\/code>codecodecodecode because they just want the feature to work right now.<\/p>\n<p>Cloudflare built a technically superior security model. They did not build a user education system. The architecture prevents a plugin from <em>stealing<\/em> data it hasn&#8217;t been granted, but it cannot prevent you from <em>giving<\/em> that data away.<\/p>\n<h2>Could a Plugin Request All Permissions? Yes. So What?<\/h2>\n<p>A malicious plugin could request every available capability. If you approve, it has the same practical access as a WordPress plugin. The difference is that in WordPress, that access is implicit and unavoidable. In EmDash, it&#8217;s explicit and requires your consent.<\/p>\n<p>This is not a flaw in the sandbox. It&#8217;s a feature of the permission model. The question is whether the average EmDash user will treat that permission dialog with the gravity it deserves.<\/p>\n<p>Consider the economics. EmDash&#8217;s full sandbox requires Cloudflare&#8217;s paid plan at $5\/month. The target audience includes developers and small publishers\u2014people who understand technical trade-offs. But as EmDash grows, it will attract less technical users. That&#8217;s when the permission model becomes a vector, not a shield.<\/p>\n<h2>What Happens When a Plugin Oversteps? Nothing\u2014Unless You Deny It<\/h2>\n<p>If a plugin tries to execute code outside its declared capabilities, the runtime throws an error. The plugin fails. Your site continues running. No data is exposed, no files are deleted, no emails are sent to attackers.<\/p>\n<p>But if a plugin declares <code>network:all<\/code>codecodecodecode and you approve it, then it can exfiltrate your content to any server. The sandbox did its job by showing you the request. The failure was yours.<\/p>\n<p>This mirrors the App Store model on iOS. Apple can&#8217;t stop you from granting location access to a flashlight app. They can only force the app to ask first.<\/p>\n<h2>The Harder Problem: Plugin Ecosystems Without Trust Infrastructure<\/h2>\n<p>WordPress has 60,000+ plugins. EmDash launched with zero. To build an ecosystem, you need to attract developers. Developers want to monetize. The GPL license in WordPress forces many developers into restrictive licensing. EmDash uses MIT, which allows closed-source plugins.<\/p>\n<p>But closed-source plugins in a sandboxed environment are hard to audit. You cannot inspect the source code to verify it only does what it claims. The permission manifest becomes your only defense. If a plugin requests <code>network:all<\/code>codecodecodecode, you have to trust the developer&#8217;s intent.<\/p>\n<p>Cloudflare&#8217;s solution to this is the 402 payment protocol and the MCP server for <a href=\"https:\/\/overcentral.com\/en\/rogue-ai-agents-liability-vacuum-97898\/\" title=\"Rogue AI agents expose liability vacuum as OpenAI faces claims\" data-iacss-internal=\"1\">AI agents<\/a>. The idea is that AI can generate plugins on demand, reducing reliance on a marketplace. But AI-generated code is even harder to audit for permission abuse.<\/p>\n<h2>Where This Architecture Breaks Down<\/h2>\n<p>The sandbox only works on Cloudflare&#8217;s runtime. If you self-host EmDash on a Node.js server, plugins run in-process without isolation. The permission model collapses. You get no protection at all.<\/p>\n<p>This is the same lock-in critics have pointed out. The feature that makes EmDash genuinely superior to WordPress requires you to stay inside Cloudflare&#8217;s infrastructure. Open source code, proprietary runtime.<\/p>\n<p>The counterintuitive truth: EmDash&#8217;s security is strongest <a href=\"https:\/\/overcentral.com\/en\/eu-cra-reporting-requirements-80362\/\" title=\"EU CRA Demands What Shipped and When You Knew\" data-iacss-internal=\"1\">when you<\/a> trust Cloudflare and weakest when you trust yourself. The plugin permission system is a marvel of modern isolation, but it cannot protect you from your own approval.<\/p>\n<h2>The Future: Permission Fatigue and the AI Agent Problem<\/h2>\n<p>EmDash is built for AI agents. The MCP server allows agents to create plugins and manage content programmatically. An <a href=\"https:\/\/overcentral.com\/en\/meta-muse-ai-agent-80441\/\" title=\"Meta Launches Muse AI Agent, Needs User Trust\" data-iacss-internal=\"1\">AI agent<\/a> could request permissions on your behalf. If the agent is compromised, or if you give it overly broad permissions, the sandbox becomes irrelevant.<\/p>\n<p>This is the next frontier. Dynamic workers were originally designed to run AI-generated code safely. EmDash reuses that technology for plugins. But AI agents don&#8217;t read permission dialogs. They execute instructions. If an agent is told to &#8220;install this plugin and grant all permissions,&#8221; it will do exactly that.<\/p>\n<p>The architecture is sound. The human element is not. EmDash solved the technical problem of plugin security. It did not solve the social problem of permission hygiene. That&#8217;s the real flaw, and it&#8217;s one no sandbox can fix.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The most dangerous plugin in EmDash isn&#8217;t the one that secretly steals your data. It&#8217;s the one that asks for everything and gets approved. Cloudflare&#8217;s new CMS has a sandbox that physically blocks unauthorized access, but it cannot stop you from granting permission to a plugin that requests too many capabilities. That&#8217;s not a technical [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":98935,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/97994.png","fifu_image_alt":"EmDash Plugin Permissions: The Real Danger Isn't What You Think","footnotes":""},"categories":[31],"tags":[],"class_list":["post-97994","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/97994.png","fifu_image_alt":"EmDash Plugin Permissions: The Real Danger Isn't What You Think","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/97994","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/comments?post=97994"}],"version-history":[{"count":2,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/97994\/revisions"}],"predecessor-version":[{"id":98936,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/97994\/revisions\/98936"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/98935"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=97994"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=97994"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=97994"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}