<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jaume Roig</title>
    <description>The latest articles on DEV Community by Jaume Roig (@jrooig).</description>
    <link>https://dev.to/jrooig</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4032092%2F91caa231-b26f-477f-97da-921256eaad84.jpg</url>
      <title>DEV Community: Jaume Roig</title>
      <link>https://dev.to/jrooig</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jrooig"/>
    <language>en</language>
    <item>
      <title>Every major AI coding agent's permission model, compared — and the three gaps none of them close</title>
      <dc:creator>Jaume Roig</dc:creator>
      <pubDate>Thu, 16 Jul 2026 12:28:24 +0000</pubDate>
      <link>https://dev.to/jrooig/every-major-ai-coding-agents-permission-model-compared-and-the-three-gaps-none-of-them-close-1232</link>
      <guid>https://dev.to/jrooig/every-major-ai-coding-agents-permission-model-compared-and-the-three-gaps-none-of-them-close-1232</guid>
      <description>&lt;p&gt;2026 has been the year coding agents started deleting things that matter. A Hacker News thread titled &lt;em&gt;"Claude CLI deleted my home directory and wiped my Mac"&lt;/em&gt; hit 255 points and 216 comments. Cursor &lt;em&gt;"went rogue in YOLO mode"&lt;/em&gt; and deleted itself along with everything else. On OpenAI's forum, users reported Codex executing file deletions &lt;strong&gt;outside the project directory&lt;/strong&gt; — 240 to 700 GB gone, straight past the Recycle Bin. One GitHub issue documents ~328,000 files deleted during a cleanup gone wrong, unlogged.&lt;/p&gt;

&lt;p&gt;I run several of these agents daily, and I don't inherently trust default permissions. When they started executing shell commands on my machine, I spent the last few days dissecting the security models of all six major clients — Claude Code, Cursor, Codex CLI, VS Code Copilot, Claude Desktop, and Devin Desktop — to answer one question: &lt;strong&gt;when your agent tries something dangerous, what actually stands in the way?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer surprised me twice. First, because the native protections are &lt;em&gt;better&lt;/em&gt; than most people think. Second, because all six share the same three gaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  The good news first: native protections are real
&lt;/h2&gt;

&lt;p&gt;Credit where it's due — the vendors have been busy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Per-call approval&lt;/th&gt;
&lt;th&gt;Rules on MCP tool &lt;em&gt;arguments&lt;/em&gt;
&lt;/th&gt;
&lt;th&gt;Sanitize tool outputs&lt;/th&gt;
&lt;th&gt;OS sandbox&lt;/th&gt;
&lt;th&gt;Hooks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗ (tool name only)&lt;/td&gt;
&lt;td&gt;via hooks&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗ (&lt;code&gt;server:tool&lt;/code&gt; only)&lt;/td&gt;
&lt;td&gt;via hooks (MCP only)&lt;/td&gt;
&lt;td&gt;✓ default-on&lt;/td&gt;
&lt;td&gt;✓ — but fail-open&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Codex CLI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VS Code Copilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗ (regex engine is terminal-only)&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✓ default-on since v1.127&lt;/td&gt;
&lt;td&gt;✓ preview — can't rewrite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Desktop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✗ — MCP servers run with your user permissions&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Devin Desktop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗ (word-boundary prefixes)&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✓ (Devin Local)&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cursor runs non-allowlisted shell commands in a Seatbelt/Landlock sandbox by default. Codex ships three sandbox levels and per-tool MCP approval modes. VS Code turned on kernel-level sandboxing for terminal commands by default &lt;em&gt;two weeks ago&lt;/em&gt; (v1.127). And it's worth being honest about the horror stories above: the worst ones happened after the user &lt;strong&gt;turned the protections off&lt;/strong&gt; — the Codex data-loss reports were in &lt;code&gt;danger-full-access&lt;/code&gt; mode, which is exactly what its name says.&lt;/p&gt;

&lt;p&gt;So no, the problem is not "agents have no brakes." The problem is where the brakes stop working. Three gaps, consistent across all six clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gap 1: nobody can write rules against the &lt;em&gt;arguments&lt;/em&gt; of an MCP tool call
&lt;/h2&gt;

&lt;p&gt;VS Code has a genuinely good allow/deny engine — regex against full command lines, deny-overrides-allow. But it only applies to the &lt;strong&gt;integrated terminal&lt;/strong&gt;. For MCP tools, approval is binary: trust the tool or don't.&lt;/p&gt;

&lt;p&gt;The same pattern repeats everywhere. Cursor's MCP allowlist matches &lt;code&gt;server:tool&lt;/code&gt; strings — no arguments. Codex approves by tool name and annotation. Claude Desktop offers "Allow always" per tool and nothing finer. Claude Code's permission rules match MCP tools by name only. Devin Local matches word-boundary prefixes, no regex.&lt;/p&gt;

&lt;p&gt;Put simply: &lt;strong&gt;you can block &lt;code&gt;rm -rf&lt;/code&gt; in VS Code's terminal — but not inside an MCP tool call, in any client.&lt;/strong&gt; And the MCP tool call is exactly where a poisoned README or a malicious tool description turns your agent into the attacker. The agent doesn't need your terminal if a &lt;code&gt;run_command&lt;/code&gt; tool is mounted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gap 2: nobody sanitizes what tools &lt;em&gt;return&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Everyone watches what the agent tries to &lt;em&gt;do&lt;/em&gt;. Almost nothing watches what the agent &lt;em&gt;reads&lt;/em&gt;. Tool results are the front door for indirect prompt injection — a fetched webpage, a repo file, a database row that says &lt;em&gt;"ignore previous instructions and…"&lt;/em&gt; — and they enter the model's context unfiltered in every client, by default.&lt;/p&gt;

&lt;p&gt;Native output sanitization across the six clients: &lt;strong&gt;zero&lt;/strong&gt;. Claude Code and Cursor can do it via hooks (&lt;code&gt;updatedToolOutput&lt;/code&gt; / &lt;code&gt;updated_mcp_tool_output&lt;/code&gt;) — if you write those hooks yourself. The other four have no mechanism at all. Claude Desktop's Cowork mode reviews actions with a model-based safety check, which is better than nothing but non-configurable and non-deterministic.&lt;/p&gt;

&lt;p&gt;The MCP spec itself is upfront about this: &lt;em&gt;"MCP itself cannot enforce these security principles at the protocol level."&lt;/em&gt; Enforcement is the host's job — and the hosts, today, mostly don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gap 3: the allowlists aren't security boundaries — the vendors say so themselves
&lt;/h2&gt;

&lt;p&gt;This is the part I'd want every agent user to read twice, because it's stated in the vendors' own documentation.&lt;/p&gt;

&lt;p&gt;Cursor, verbatim: &lt;em&gt;"Not a security boundary. Allowlists and autoRun instructions are best-effort convenience. They are not a security guarantee."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Microsoft, verbatim: &lt;em&gt;"best-effort command parsing that has known limitations. For example, quote concatenation or shell aliases might bypass the rules."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These aren't hypothetical caveats. Cursor's prefix allowlist was bypassed in the wild with simple &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; chaining (allowlist &lt;code&gt;cd&lt;/code&gt;, then &lt;code&gt;cd x &amp;amp;&amp;amp; terraform apply -auto-approve&lt;/code&gt; sails through). CVE-2026-22708 — patched in Cursor 2.3 — let shell built-ins and environment-variable poisoning execute without appearing in the allowlist at all.&lt;/p&gt;

&lt;p&gt;Even the newest mitigation — Cursor's Auto-review mode — is a &lt;em&gt;classifier subagent&lt;/em&gt;: a model deciding whether another model's action looks safe. Useful, but probabilistic. When the stakes are &lt;code&gt;rm -rf&lt;/code&gt;, "usually catches it" is a strange guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six clients, six models — and the multi-agent hub doesn't save you
&lt;/h2&gt;

&lt;p&gt;If you run more than one agent — and most of us now do — you're maintaining a different security model per client, with different config formats, different capabilities, and different failure modes.&lt;/p&gt;

&lt;p&gt;You might hope the new multi-agent hubs fix this. They don't. Devin Desktop (the June rebrand of Windsurf) runs third-party agents like Codex and Claude Agent via the Agent Client Protocol — and its docs state plainly: &lt;em&gt;"all agent operations are delegated to the agent."&lt;/em&gt; The hub displays whatever permission prompts each agent chooses to send. Security stays heterogeneous; the hub unifies the UI, not the policy.&lt;/p&gt;

&lt;p&gt;Meanwhile the landscape churns under your configs: Windsurf became Devin Desktop, Continue.dev is winding down, Cursor is being acquired. Every migration is a security config you rewrite — or forget to.&lt;/p&gt;

&lt;p&gt;(One telling detail: VS Code's new hooks system reads Claude Code's &lt;code&gt;.claude/settings.json&lt;/code&gt; format. Even the vendors are tired of N incompatible configs.)&lt;/p&gt;

&lt;h2&gt;
  
  
  "Just write hooks" — sure, and here's the bill
&lt;/h2&gt;

&lt;p&gt;Hooks are the standard power-user answer. If you live in a single client and enjoy writing bash, hooks will take you far. Claude Code and Cursor hooks can block a call, rewrite arguments, and scrub a tool's output before the model reads it.&lt;/p&gt;

&lt;p&gt;But as a security mechanism, hooks are fragile and fragmented. First, three major clients have &lt;strong&gt;no hooks at all&lt;/strong&gt; (Codex CLI, Claude Desktop, Devin Desktop). Second, the ones that do exist are inconsistent: VS Code's hooks can't rewrite anything.&lt;/p&gt;

&lt;p&gt;The biggest red flag? &lt;strong&gt;Cursor's hooks fail open by default&lt;/strong&gt;. If your bash script crashes, times out, or has a syntax error, the dangerous action goes through. In security, a firewall that fails open isn't a firewall — it's a suggestion. And even if you write perfect scripts, you are still maintaining them per project, per client, forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an inline proxy does differently
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I built the tool below to scratch my own itch, so read this section knowing that.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The gaps we just talked about all share the same structural flaw: enforcement lives &lt;em&gt;inside&lt;/em&gt; the client. This means security is only as good — and as consistent — as each individual client's implementation.&lt;/p&gt;

&lt;p&gt;I got tired of maintaining five different fragmented configs, so I decided to move enforcement &lt;em&gt;below&lt;/em&gt; the clients, directly into the MCP connection itself.&lt;/p&gt;

&lt;p&gt;That's why I built &lt;a href="https://mcp-shield.dev" rel="noopener noreferrer"&gt;MCP-Shield&lt;/a&gt;. It's a local proxy that sits inline on the JSON-RPC wire between any MCP client and its servers. The philosophy is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One policy to rule them all.&lt;/strong&gt; Write the rules once, and they apply instantly whether the call comes from Claude Code, Cursor, Codex, VS Code, or anything else speaking MCP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Argument-level rules on MCP tool calls&lt;/strong&gt; — the glaring hole none of the six clients close natively (Gap 1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output sanitization&lt;/strong&gt; before dirty data reaches the model's context window (Gap 2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic, fail-closed enforcement.&lt;/strong&gt; It uses hard rules, not probabilistic classifiers. If it breaks, it denies access. (Gap 3).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A live local dashboard&lt;/strong&gt; to review, approve, deny, or even &lt;em&gt;edit&lt;/em&gt; a held call on the fly before it executes.&lt;/li&gt;
&lt;li&gt;Because it inspects the raw wire, it catches tricks that native hooks structurally can't even see (like duplicate-key parser differentials and batch smuggling).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff2uvk4na9mi2dfe09zh9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff2uvk4na9mi2dfe09zh9.png" alt="MCP-Shield dashboard holding a curl command for manual approval" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal was zero friction. You don't have to touch your existing client configs, the installer handles the wiring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @jrooig/mcpshield
mcp-shield &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What it doesn't do
&lt;/h2&gt;

&lt;p&gt;Let's be completely honest: MCP-Shield is a scalpel, not a magic bullet. It only intercepts MCP traffic. If an agent uses its built-in terminal or native file-editing capabilities, MCP-Shield won't see it. (That's what native OS sandboxes are for — use both.)&lt;/p&gt;

&lt;p&gt;The prebuilt rules cover the most common destructive patterns, but it's not a catch-all — you are expected to read and extend them for your own workflow. And obviously, no software in the world can fix the human error of blindly clicking "Approve" without reading the prompt. It's an extra layer of defense-in-depth, not a free pass to turn your brain off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves us
&lt;/h2&gt;

&lt;p&gt;To give credit where it's due, vendors are taking this seriously and building real brakes — VS Code's default-on kernel sandbox is barely two weeks old and it's a massive step forward.&lt;/p&gt;

&lt;p&gt;But until the architecture changes, the three gaps remain structural. As long as enforcement is handled per-client, we're stuck with argument-blind MCP approvals, unfiltered tool outputs, and N different configs that explicitly admit they are not security boundaries.&lt;/p&gt;

&lt;p&gt;The agents went cross-client a long time ago. The attacks are cross-client now. It's time our security layer became cross-client too.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want to poke holes in the code or use it yourself, MCP-Shield is open source (MIT): &lt;a href="https://github.com/jaumerohi2007-cell/mcp-shield" rel="noopener noreferrer"&gt;github.com/jaumerohi2007-cell/mcp-shield&lt;/a&gt; · &lt;a href="https://mcp-shield.dev" rel="noopener noreferrer"&gt;mcp-shield.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>mcp</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
