How do you stop an AI agent from being overprivileged on a Databricks MCP or Genie connection?

Five steps, in sequence.

1. Short-lived, single-audience tokens. Use the RFC 9068 JWT access-token format with an aud claim pinned to one MCP server, and require the RFC 8707 resource parameter so a token minted for Genie cannot be replayed against your SQL warehouse. 2. Token exchange over passthrough. When the agent's identity has to reach a downstream API, swap the token via RFC 8693 token exchange so the downstream sees a correctly-audienced, scope-narrowed credential rather than a borrowed user token. 3. Least privilege, then step up. Start with the smallest scope the task needs and ask for more only after a 403, instead of granting broad session scope up front because it is convenient. 4. Per-call authorization. Re-derive what the agent may do on every invocation, so a revoked grant is dead on the next call instead of at token expiry. 5. Untrusted tool text. Treat every tool description and tool output as hostile input; it lands in the model with ambient authority and no sanitization.

Databricks native governance covers pieces of this. What it does not give you, per the public docs, is a per-call scope ceiling or a next-call kill. The rest of this post explains why that matters and how to close it. Read it as an engineering threat model rather than a full compliance checklist.

What "overprivileged" actually means on an MCP connection

An agent is overprivileged when the token or grant it holds lets it invoke more tools, or reach more data, than the task in front of it requires, and that authority just sits there for the whole session. Ask Genie one question about last quarter's churn. If the connection scope is broad, that same session can now read every table the scope touches. Nothing narrowed after the first answer.

The MCP Authorization spec is refreshingly honest about where it stops. It makes authorization optional and defines the MCP server as an OAuth 2.1 resource server, meaning it validates tokens issued by a separate authorization server. It does not define per-tool-call authorization ceilings. So the standard gives you a clean way to confirm a token is valid and correctly addressed, but says nothing about re-checking authority as the agent works. Session-long authority becomes the default, and that default is exactly what an attacker inherits the moment they hijack the agent's goal.

What the MCP Authorization spec requires, and what it leaves out

Two requirements in that spec are load-bearing, and I see people skip both.

Audience binding is mandatory. The spec says MCP servers MUST validate that access tokens were issued specifically for them as the intended audience, per RFC 8707, and that MCP clients MUST NOT send tokens other than ones issued by the server's own authorization server. Servers MUST NOT accept or transit any other token. That is the spec-level ban on token passthrough, and passthrough is what creates confused-deputy risk. If your Databricks MCP server happily forwards whatever bearer string shows up, congratulations, you built the confused deputy yourself.

Resource indicators are mandatory. Clients have to implement RFC 8707, and the resource parameter must appear in both the authorization and token requests, naming the specific server by canonical URI. One token, one downstream.

The gap is the interesting part. Scopes are coarse (think files:read and files:write) and they get negotiated once, at token issuance. The step-up flow lets a client ask for more scope after an HTTP 403 insufficient_scope, which is good, but nothing re-evaluates scope on each tool call. The spec is a living, date-versioned document, and these audience and no-passthrough requirements have been in force since the June 2025 revision, so they predate this post. The clause numbers may move as it is revised, but the requirement has held.

What Databricks native governance gives you (and what it doesn't)

Databricks announced managed MCP servers with Unity Catalog integration in June 2025. The managed set covers Genie (scope genie), AI Search (ai-search), Databricks SQL (sql), and Unity Catalog functions (unity-catalog), with on-behalf-of-user authentication out of the box. The docs put it plainly: "Unity Catalog enforces permissions, so agents and users access only the tools and data you grant them." That is good hygiene, and you should use it.

Register an MCP server as a Unity Catalog securable and admins get grants (who can invoke it), tool selection (which tools it exposes), service policies (allow, deny, or approve individual tool calls), and audit logging. Unity AI Gateway layers runtime traffic and behavior governance across models, agents, servers, and tools, and it handles OAuth token exchange and refresh with on-behalf-of token passing behind the scenes.

The boundary worth naming is what those grants do not cover. They are scoped by role, permission, and tag, and service policies act at the grant and service layer. The documented model does not describe a per-call scope ceiling re-derived on every tool invocation, nor mid-session, next-call token revocation; tokens expire on their own schedule. I am not claiming Databricks cannot do these things, only that the public docs do not describe them, and any agent operating outside the Gateway is ungoverned entirely. Check the newest docs before you bet on it.

The threats: tool poisoning, the lethal trifecta, and real incidents

In April 2025 Simon Willison laid out the core problem: combine private data, exposure to untrusted content, and a way to exfiltrate, and any tools that act on the user's behalf become attacker-controllable. As he put it, "you're effectively allowing attackers to make those tools do whatever they want." He later named that combination the "lethal trifecta." The Invariant Labs WhatsApp MCP attack he covers exfiltrates message history, and he notes an attacker can even base64-encode it to hide the theft. He also notes the field still lacks convincing mitigations for prompt injection after more than two and a half years of trying. A Databricks MCP connection carries all three ingredients by design.

The incidents below are worth keeping straight, because the labels get muddled.

  • EchoLeak (CVE-2025-32711) was proof-of-concept research rather than an in-the-wild breach. Disclosed by Aim Labs in June 2025 at CVSS 9.3, it was a zero-click indirect prompt injection in Microsoft 365 Copilot. One crafted email, no clicks, and Copilot could read internal files and exfiltrate them. Microsoft patched it server-side with no confirmed exploitation in the wild. OWASP lists it among its ASI01 Agent Goal Hijack examples.
  • MCPoison (CVE-2025-54136) came from Check Point Research, publicly disclosed in early August 2025. Cursor approved an MCP config once and then stopped re-validating, so an attacker with write access to a shared repo could swap the approved config for a malicious command and keep persistent code execution. It was fixed on July 29, 2025 in Cursor 1.3, which re-prompts on any config change.
  • AgentFlayer, demonstrated by Zenity at Black Hat USA in 2025, chained zero-click and one-click prompt injection against enterprise agents, including secret exfiltration through a Jira MCP server in Cursor. This too was research, a live-fire proof that the chains work outside a slide deck.
  • Tool poisoning is now its own documented class: malicious instructions hidden in tool descriptions or MCP mechanisms, read by the model with full ambient authority and no sanitization, plus definitions that can mutate after approval.

One thread runs through all of it: trust decided at connect time does not hold at run time. OWASP's Top 10 for Agentic Applications, published December 9, 2025, ranks Agent Goal Hijack (ASI01) first and lists Identity and Privilege Abuse (ASI03) as its own category, which puts overprivilege squarely on the official list.

Databricks MCP security best practices: how to prevent overprivilege

A few concrete moves, roughly in the order I would apply them. Issue RFC 9068 JWTs with an aud bound to a single server, plus the RFC 8707 resource parameter on every authorization and token request, so a stolen Genie token is worthless against your SQL warehouse. Reject any token your MCP server did not get from its own authorization server, and give downstream calls an RFC 8693 exchange that narrows scope and re-audiences the token, so no borrowed bearer string ever transits. Advertise only the scopes you actually need and let the client escalate after a 403, instead of front-loading broad session scope to save a round trip.

Then re-check trust at run time. MCPoison worked precisely because approval was a one-time event, so re-prompt or re-authorize on any config or tool-definition change, validate the OAuth iss (RFC 9207) and state on every callback to blunt mix-up and confused-deputy attacks, and never let tool text steer the agent unchecked. Finally, constrain the blast radius in the data plane: assume some prompt injection lands, and ask what the agent can actually reach when it does.

That last question is where native grants and a per-call authorization layer stop overlapping. For the wider attack surface, the sibling MCP server security threat model walks each class and its control, and MCP prompt injection covers the injection half in depth.

The data-plane angle: what the agent can physically reach when a control fails

Every control above governs what the agent is allowed to do. The other half is what it can physically reach when a control fails, and that is the layer most MCP guides never touch.

Tokenize sensitive fields at ingest. If PII becomes a token at the point of storage, a hijacked agent that slips past every authorization check pulls back tokens instead of raw Social Security numbers or account balances, so the exfiltration in an EchoLeak-style attack walks off with ciphertext-shaped noise. This complements Unity Catalog rather than replacing it: Unity Catalog governs who may invoke a tool, and field-level tokenization limits what the pulled data is worth once it leaves the boundary. DataShield builds this as an evidence and authority layer around your warehouse, with an encrypted connection vault holding the credentials so the agent never touches raw warehouse secrets. The ontology is where you declare which fields count as sensitive in the first place.

The practical stance: native governance has to cover reach as well as intent, and tokenization is what makes a breach of that governance survivable.

Per-call authorization and proof it happened

The missing piece under the Databricks model is a ceiling that gets re-derived on every tool call, plus revocation that bites immediately. DataShield Auth implements that as a per-call dispatch pipeline. For each invocation it applies a scope ceiling, then an authority tier, then a mid-session revocation re-check, then metered dispatch, then a sealed, hash-chained audit entry. The practical effect is the one that matters during an incident: a token stolen at 9:00 is dead at 9:05, killed on the very next call rather than whenever it would otherwise expire. Delegation runs on-behalf-of with the same scope ceilings, so a sub-agent can never exceed the authority of the agent that spawned it.

Worth a note on where policy engines belong, since it trips people up. Cedar-style policy fits admin, platform, config, and token decisions well, but it is not the per-tool dispatch mechanism; that job belongs to the dispatch pipeline. Mix the two layers and you end up re-evaluating a policy document on a hot path and calling it authorization.

Auditors and incident responders will not take your word for it, so every call seals into a tamper-evident, hash-chained record you can verify after the fact. When someone asks which agent read which table at 9:03, you have a cryptographic answer rather than a log you hope is complete. To be straight about the limits, this is DataShield's described capability set and there is no SOC 2 attestation yet, so evaluate it on its engineering merits and confirm the claims for yourself.

Two walkthroughs of MCP on Databricks and Genie, plus how to vet an MCP server.

MCP on Databricks: Build Governed Enterprise AI Agents video

MCP on Databricks, governed agents (VectorLab)

Connect Databricks Assistant to MCP Servers (Genie Space) video

Databricks Assistant to MCP and Genie (Data Science Basics)

MCP Security: Vetting Servers to Mitigate Tool Poisoning video

Vetting MCP servers for tool poisoning (JeredBlu)

Frequently asked questions

Does Databricks Unity Catalog already stop an agent from being overprivileged?

It helps, though not all the way. Unity Catalog and Unity AI Gateway govern who can invoke an MCP server, which tools it exposes, and can allow, deny, or approve individual tool calls, all scoped by role, permission, and tag. Per the public docs, that model does not re-derive a per-call scope ceiling on every invocation and does not kill a token on the next call after revocation; tokens simply expire on their own schedule. Treat native governance as the necessary base and add per-call authorization on top.

What is token passthrough and why is it dangerous on an MCP server?

Passthrough is when an MCP server forwards whatever bearer token it receives to a downstream API instead of validating and exchanging it. The MCP Authorization spec forbids it: servers must validate that tokens were issued for them as the intended audience (RFC 8707) and must not accept or transit any other token. Passthrough creates confused-deputy risk, where the server uses its own trust to act on an attacker-supplied credential. Exchange tokens via RFC 8693 instead.

What's the difference between least-privilege scope and per-call authorization?

Least-privilege scope is negotiated once, at token issuance, and can be stepped up after an HTTP 403 insufficient_scope error, but it stays fixed for the session between those events. Per-call authorization re-derives what the agent may do on every single tool invocation, which lets a revoked grant die mid-session on the next call rather than at token expiry. The MCP spec standardizes the scope negotiation but leaves per-call authorization for you to implement.

Was EchoLeak an actual breach of Microsoft 365 Copilot?

No. EchoLeak (CVE-2025-32711, CVSS 9.3) was proof-of-concept research disclosed by Aim Labs in June 2025, a zero-click indirect prompt injection that could make Copilot read and exfiltrate internal files. Microsoft patched it server-side and reported no confirmed exploitation in the wild. OWASP lists it among its ASI01 Agent Goal Hijack examples. What it demonstrated was the mechanism at work, without any real-world compromise behind it.

How does field tokenization help if my agent still gets hijacked?

It limits the blast radius. If sensitive fields are tokenized at ingest, an agent that slips past authorization and exfiltrates data walks off with tokens rather than raw PII, so the stolen payload is worthless without the separate detokenization authority. It complements Unity Catalog access control rather than replacing it: the access grant governs whether the agent may act, while tokenization governs how much a stolen result is worth once it crosses the boundary.