Est.
MCP SecurityLong read

Separation of Privilege in MCP Tool Authorization

Most MCP deployments lack access scoping, leaving agents vulnerable to confused-deputy attacks.

Staff Writer · · 11 min read
Cover illustration for “Separation of Privilege in MCP Tool Authorization”
MCP Security · August 16, 2026 · 11 min read · 2,537 words

Separation of privilege in MCP tool authorization means drawing hard lines around what each agent, role, and server can touch, and enforcing those lines on purpose. Without that discipline, every tool connection an agent can technically reach becomes a tool connection it actually does reach, and there's no boundary left to speak of.

Anthropic introduced the Model Context Protocol in November 2024 as a JSON-RPC interface, a standard, model-agnostic way for agents to call external tools, pull from data sources, and run workflows. It caught on fast. By 2025 the ecosystem had crossed 10,000 public servers and 97 million monthly SDK downloads, with Anthropic, OpenAI, Google, and Microsoft all backing it under Linux Foundation governance.

That scale matters because of what it implies about exposure. Every one of those 10,000-plus servers is a door an agent might walk through. MCP solved connectivity. It did not solve permission.

Here's the conceptual gap, stated plainly: MCP standardizes how an agent calls a tool. It says nothing about whether that agent should be allowed to make the call in the first place. Without explicit scoping, a connected agent defaults to being a capable agent, and capability quietly merges with permission until they're the same thing. That collapse is the whole problem this piece is about, and everything below builds toward the architecture that fixes it: credential design, gateway enforcement, and the observability to prove it's working.

Where the principle of least privilege comes from and what it actually requires

Least privilege isn't a new idea. The classical version says a subject gets only the privileges essential to its assigned task, nothing more. Any access right that isn't strictly necessary shouldn't be granted, and if a task temporarily needs elevated rights, those rights get dropped the moment the task ends.

The engineering version of this is separation of privilege: split a system into components running at different trust levels, and make them talk to each other through narrow, defined interfaces. The canonical example comes from Provos, Friedl, and Honeyman's work on OpenSSH, where a privileged monitor process and an unprivileged slave process communicate over a socket pair. The slave does the risky work with almost no authority; the monitor holds the authority but does almost no risky work. Neither side has to trust the other completely.

Strip it down and the principle demands three things. Access is scoped to a task, not handed out based on who you are. Rights get granted right before they're needed and revoked right after. And components sitting at different trust levels never share credentials or borrowed authority.

Every one of those demands maps directly onto a design decision you'll make in an MCP deployment: how you scope a token, how long it lives, whether each server gets its own credential, whether your gateway actually isolates one trust zone from another. Keep that mapping in mind, because it's the thread running through the rest of this piece.

Why static least-privilege models break when the subject is an AI agent

Traditional least privilege assumes you can design access ahead of time. A human has a role. The role maps to a fixed set of tasks. The tasks map to a stable set of permissions. You set it once, review it periodically, move on.

Agents break all three assumptions at once. They switch tasks mid-run based on a prompt or a piece of retrieved context, not a job description. They touch multiple systems in sequences nobody mapped out in advance. And because they reason and plan, their access needs emerge as they go instead of getting specified up front.

The result is predictable, and I've watched it happen inside more than one org: overpermissioning creeps in. Someone widens a scope to unblock a demo. Nobody narrows it back afterward, because nobody's sure what's still in use. That debt piles up invisibly, quietly, until the agent is sitting on far more access than anyone actually intended to give it. Authentication tells you who the agent is. It tells you exactly nothing about what it should be allowed to do once it's in.

So what does least privilege look like when the subject is an agent instead of a person? Access has to become task-based, scoped to the specific action being taken right now. It has to be time-bound, expiring the instant the task wraps. And it has to be identity-driven, with every single action traceable to a verifiable identity, not just a session.

Arthur AI's rule of thumb is a decent gut check here: an agent should hold fewer permissions than the human who built it. It's not a formal policy, just a useful floor when you're setting initial scope baselines and want something more concrete than "seems fine."

The architectural upshot: a permission set fixed at the session level cannot deliver least privilege for an agent. The math doesn't work. Authorization has to operate at the level of the individual action, not the login.

The confused deputy problem and why it is the central authorization failure in MCP

Venn diagram: MCP Authorization: Confused Deputy vs. Privilege Separation. Compares Confused Deputy Risk and Privilege Separation; overlap: Shared Concerns.

Norm Hardy named this in 1988, and the original example is almost quaint now. A compiler has permission to write to a log file. A user tricks it into redirecting its output to overwrite a billing file instead. The compiler complies, because it has the permission; it just has no idea it's being used against its owner's interests.

Swap the compiler for an LLM holding credentials to a production database, an email service, and a payment gateway, and you've got the modern version. Same failure, much higher stakes.

Here's how it plays out inside MCP specifically. An agent is often issued a single, session-level token that spans several tools and data scopes at once. Somewhere along the way, a malicious instruction, buried in a prompt, a retrieved document, or a tool's own response, redirects the agent's authority toward a target nobody intended. The agent goes along with it. It isn't broken. It's just confused about whose authority it's actually exercising in that moment.

This isn't hypothetical. Invariant Labs documented a confused-deputy issue in the GitHub MCP server in May 2025: an agent holding one token that spanned both public and private repositories got steered, through a malicious public issue, into reading data from a private repo. One over-scoped, reused credential, crossing a boundary it should never have been able to cross.

Multi-hop setups make this worse, not better. A single user request might pass through an orchestrating agent, one or more intermediate MCP servers, and a downstream tool, and every hop along the way is making a decision on behalf of the original caller. Each hop is its own potential confused deputy. Authentication only ever answers "who are you." What an MCP deployment actually needs answered is "who authorized this specific action, through what chain, and with what scope."

And this isn't a fringe risk. The State of MCP Server Security 2025 found that only 18% of MCP server deployments implement any form of access scoping for tool permissions. That means in the large majority of live deployments, the confused deputy isn't a theoretical edge case. It's the default state of the system.

Diagram: The Authorization Gap: 82% of MCP Deployments Have No Access Scoping. Visualizes: A single stark stat callout showing the security gap in live MCP deployments: only 18% of MCP server deployments implement any form of access scoping for…

Token passthrough as the anti-pattern that makes the confused deputy inevitable

Token passthrough is exactly what it sounds like: the caller's inbound token gets forwarded, unmodified, straight to a downstream MCP server. It's an easy pattern to fall into. The token's already sitting right there, and passing it along takes zero extra infrastructure.

It's also structurally unsafe, for a reason that's easy to miss if you're moving fast. That inbound token was scoped for the caller's session, not for whatever narrow thing the downstream server actually needs to do. Forwarding it hands the downstream server far more authority than the interaction calls for. If that server turns out to be compromised, malicious, or just confused by a bad instruction, it's now holding a credential that reaches way past where it should. The MCP authorization spec doesn't hedge on this: token passthrough is a MUST NOT.

The fix is token exchange, laid out in RFC 8693. Instead of forwarding the raw token, the gateway swaps it for a new one, audience-bound and scoped specifically to the target server. The original user's identity doesn't disappear in the swap; it's preserved through an act claim, the on-behalf-of pattern, so the full chain of delegation stays auditable end to end. Each downstream call only carries what that specific call needs. Nothing travels further than it has to.

Resource Indicators, from RFC 8707, do complementary work here: they bind a token to a specific resource URI. That directly closes off the confused deputy's favorite move, redirecting a valid credential toward a target it was never meant to touch.

Which makes the gateway itself the load-bearing piece of this whole architecture. It's not a nice-to-have sitting in front of your servers. It's the exact point where token exchange happens or doesn't, and where a confused deputy either gets stopped cold or sails right through.

Diagram: Token Passthrough vs. Token Exchange: What Changes at the Gateway. Visualizes: A before/after flow showing two paths through a gateway to a downstream MCP server.

What the NSA's May 2026 advisory says MCP deployments must enforce

On May 20, 2026, the NSA's Artificial Intelligence Security Center put out a Cybersecurity Information Sheet called "Model Context Protocol (MCP): Security Design Considerations for AI-Driven Automation." It's the first formal intelligence-community advisory aimed squarely at the MCP ecosystem, and it opens with the finding that matters most here: MCP doesn't define how a session maps to a verifiable identity, authentication is optional rather than required, and role-based access control was never built into the protocol at all. The spec's designers left authorization to implementers. Most implementers, per that 18% figure above, haven't built it.

The advisory gets specific about what's required, and it's worth walking through each piece.

Least-privilege tokens per action: every tool call should carry a scoped credential covering exactly what that one action needs, not a session-level token that grants everything the agent is generally allowed to do. This is the per-action token exchange requirement, stated with real authority behind it now.

Data classification segregation: tools and models need to align with data classification zones. Public tools handle public datasets. Anything touching sensitive or regulated data, health records, financial data, controlled unclassified information, needs explicit, separate controls. The line between zones isn't just a data policy anymore; it's an authorization boundary.

Unverified task propagation: tasks that move between MCP servers or agentic components without validation of origin, scope, or intent open the door to overreach, context leakage, and tools firing when they shouldn't. Every hop in a multi-agent chain has to check what it received before acting on it, full stop.

Observability as a requirement, not a nice option: every tool and model invocation should get logged, exact parameters, the identities involved, and where possible, cryptographic hashes of the results. These logs are the backbone of any real forensic response, but only if they're captured live. Reconstructing them after the fact is too late.

What the advisory adds beyond the checklist is the framing: MCP's adoption outran its security safeguards. The vulnerability didn't show up recently; it existed the moment a server went live without governance. The NSA putting this in writing means the gap is now treated as a national security concern, not just an engineering trade-off someone can defer to next quarter.

How MCP's own specification encodes privilege separation in its 2025–2026 updates

The protocol itself has been catching up, and it's worth giving credit where it's due. As of the June 2025 spec update, MCP servers are officially classified as OAuth Resource Servers. That brings protected resource metadata into the protocol, a way to discover what authorization a connection will require before that connection gets established.

The November 25, 2025 spec revision went further, adding pieces that directly implement privilege separation. Native scope definitions, under SEP-835, let a tool declare up front exactly what access it needs, so clients and gateways have something concrete to enforce against. Short-lived tokens with proof-of-possession, via DPoP under RFC 9449, close off replay attacks; a stolen token is useless without the private key that goes with it. Rich Authorization Requests, from RFC 9396, allow fine-grained scoping down to specific resources or tool parameters, not just "this agent can use this server" but "this agent can call this method, with these parameters, on this resource."

Then came the July 2026 revision, which pushed enforcement down to the gateway layer. New Mcp-Method and Mcp-Name headers let different tool calls get routed through different authorization policies before the request ever reaches server code. That's a real shift: policy now applies per tool call instead of per session. The gateway sees which method is being invoked and which tool is targeted, and it can hand out a distinct credential and scope for each one.

The spec has done its part. What's left is adoption, and that's on the implementers. An organization not using these mechanisms isn't sitting in some neutral, wait-and-see position; it's operating without protections the protocol now explicitly offers.

Privilege at the definition layer: tool poisoning and rug pull attacks

Token scoping handles who can call what. It doesn't handle a tool that was granted legitimate access and then quietly changes what it does with it. That's a different failure mode entirely, and it's just as dangerous.

Two patterns show up here. Tool poisoning embeds malicious instructions inside a tool's description or its responses, turning the tool's own definition into the attack surface. Rug pulls work differently: an attacker deploys a server that looks completely legitimate, gets it approved, then modifies the tool's definitions or behavior after the fact. The approval was granted for the original version. The modified version inherits that trust anyway, because nothing checked.

This already happened. In September 2025, a widely installed email-service MCP package, Postmark's, pushed an update that silently BCC'd every email an agent sent through it to a domain the attacker controlled. It passed review at install time, because at install time it behaved exactly as advertised. The malicious behavior only showed up in a later version.

Standard access controls miss this entirely, and it's worth being blunt about why: RBAC and token scoping check identity and scope at call time. Neither one checks whether the tool being called is still the tool that got approved in the first place.

The countermeasure researchers have proposed is ETDI (Bhatt, Narajala, and Habler, arXiv:2506.01333, June 2025), and it's a genuinely useful model. Tool definitions get cryptographic identity: sign the definition, and any change to it invalidates the signature outright. Definitions become immutable and versioned, tied to API contract hashes, so a changed tool is treated as a different tool requiring fresh approval, never inherited trust. OAuth 2.0 scopes get conveyed through signed JWTs tied to specific versions, so a token issued for version 1.0 simply doesn't work against version 1.1. And a policy engine sits on top of all of it, capable of denying a specific invocation even when the tool's definition checks out, if the surrounding context violates policy.

Put it together and the governance implication is straightforward: privilege separation in MCP can't stop at tokens and scopes. It has to reach the definition layer too, because a tool that behaved yesterday is not a guarantee about how it behaves today.

Sources

  1. auth0.com
  2. coalitionforsecureai.org
  3. media.defense.gov
  4. arxiv.org
  5. arxiv.org
  6. arxiv.org
  7. modelcontextprotocol.info
Filed underMCP Security

More in MCP Security