How a Snowflake MCP server actually works
Snowflake announced managed MCP servers in July 2025. They reached public preview in October 2025. And GA in November 2025. The goal is simple. It lets an AI agent pull data from a Snowflake account without you standing up your own server. The managed server bundles four tool types. Cortex Analyst turns natural language into SQL over semantic views, and Cortex Search does semantic search over unstructured data. Cortex Agents lets you call an agent as a tool, plus plain direct SQL execution.
Two details matter most for security. First, you can lock down the SQL execution tool with a read_only option. Second, each tool call runs inside Snowflake's governance rules, under RBAC, as the role that logged in. Snowflake frames the managed server as a governed gateway. The same masking policies and row level security that guard your tables guard tool access too. There is no extra permission model. That's a real plus. It is also why overprivilege is a design question here, not something you bolt on later.
Why one natural-language question can overprivilege an agent
Think about how a human analyst used to hit production. They wrote SQL. Buried in that SQL was a LIMIT, a WHERE, some instinct that says "I don't need ten million rows to answer this." That habit kept a lid on how much data any one query gave back.
Route the same question through a Cortex or SQL MCP tool, and the habit is gone. One harmless prompt, say "summarize our highest-value customers," can turn into a query. That query can pull large amounts of regulated data, such as PII or PHI, into the model's context. It happens in one call. The tool runs under the RBAC of the role that connects it. So the agent sees just what that role can see, and nothing narrows it further. If the role behind your MCP server can read raw CUSTOMERS, so can any agent that reaches it, hijacked or not. The role's grants are the blast radius.
What the MCP authorization spec requires
The MCP authorization spec, version 2025-11-25, is where the guardrails become rules you must follow. A protected MCP server acts as an OAuth 2.1 resource server. The client acts as an OAuth 2.1 client. Authorization is optional, but HTTP transport servers SHOULD conform. The parts that matter most:
- Servers MUST check that access tokens were issued just for them (audience binding, per RFC 8707).
- Clients MUST send the RFC 8707
resourceparameter on authorization and token requests. - Tokens MUST ride in the
Authorization: Bearerheader on each request. They MUST NOT show up in the URI query string. - Clients MUST use PKCE with S256.
- Authorization servers SHOULD issue short lived access tokens.
There's a hook for keeping scope small too. Clients follow least privilege using the scope from the server's WWW-Authenticate challenge. Step-up authorization returns an HTTP 403 insufficient_scope, when more access is truly needed. Ask for only what the task needs, and step up only when a real 403 tells you to.
Why token passthrough is the trap
The spec is blunt about one bad pattern. An MCP server MUST NOT accept tokens that weren't issued for it. And when it calls an upstream API, it MUST NOT forward the token it got from the client. It has to use a second token, issued by the upstream authorization server.
Skip that, and you've built a confused deputy. Your MCP server sits on broad Snowflake access. It starts accepting or forwarding tokens minted for something else. Now the audience check that was supposed to bound access is just for show. Audience binding plus no passthrough is the pair that keeps one server from turning into a master key. You want both in place. For more on this, see MCP server security.
Snowflake's token model, and where teams get it wrong
Most Snowflake MCP setups authenticate with Programmatic Access Tokens (PATs) or a shared service account. PATs work fine as a basic tool, if you set them up well. Per Snowflake's docs, a PAT can be restricted to a single role (ROLE_RESTRICTION). The token's role decides object ownership and what it can reach. The user must sit under a network policy, unless an authentication policy relaxes it. You set expiry with DAYS_TO_EXPIRY. There's also MINS_TO_BYPASS_NETWORK_POLICY_REQUIREMENT, an escape hatch you should barely use. Plus a known cap of 15 PATs per user, counting disabled ones.
The problem is rarely the tool itself. It is almost always the setup. Long expiry, a role that is too broad, or one shared service account fanned out across each agent you own. A PAT defaults to a 15-day expiry, and can be stretched all the way to 365. So DAYS_TO_EXPIRY can be short. Teams set it long and forget it exists. A long lived, broadly scoped, shared token is just the kind of credential attackers hunt for. It is often the one they find.
The incidents that make this concrete
Two real events. Here's just what each one is.
UNC5537 (in-the-wild, 2024). Mandiant tracked a financially motivated actor. From around April 2024, it broke into roughly 165 Snowflake customer accounts. It used valid credentials that infostealer malware grabbed. Some of them reportedly dating back to 2020. There was no breach of Snowflake's own environment. The common thread was customer accounts leaning on single factor credentials, with no MFA turned on. Openly reported victims include Ticketmaster/Live Nation, AT&T, Santander, and Advance Auto Parts. The takeaway for MCP is direct. A valid credential against an overprivileged account is enough to carry the whole attack.
EchoLeak / CVE-2025-32711 (proof-of-concept). Aim Labs disclosed a zero-click indirect prompt injection chain in Microsoft 365 Copilot. Reported openly on June 11, 2025, carrying CVSS 9.3. They named the technique "LLM Scope Violation." Untrusted email content makes the model reach for and steal special in-context data. Per the vendor reporting, it was reported to Microsoft in January 2025 and patched server side by around May 2025. Aim Labs states it is not aware of any customers being impacted. This was research, not an active campaign. It shows how a hijacked agent can turn its own access against you.
Where OWASP's agentic Top 10 fits
On December 9, 2025, the OWASP GenAI Security Project released the OWASP Top 10 for Agentic Applications. The first flagship list built for autonomous agents. ASI01 Agent Goal Hijack ranks number one. OWASP puts prompt injection style attacks in this bucket. Hidden instructions in emails, documents, RAG results. It cites EchoLeak as an example. ASI02 Tool Misuse and Exploitation and ASI03 Identity and Privilege Abuse round out the ones that matter here.
You don't have to imagine the tool misuse case. Researchers showed a GitHub MCP prompt-injection. A malicious public issue steered an agent into stealing private repository data, using the agent's own permissions. Map the pattern onto Snowflake. A broadly scoped role or shared service account (ASI03) lets a hijacked agent (ASI01) take over. It turns a harmless natural language request into unapproved bulk data access (ASI02). The overprivileged MCP role is the pivot that wires all three together.
Snowflake MCP server authorization best practices
Here's the checklist I'd really run, ranked from most useful to least.
- Bind each token to that one MCP server with RFC 8707 audience checks, and refuse token passthrough. This closes the confused deputy path.
- Issue short lived tokens, and retire long lived shared PATs and service accounts. One credential per agent identity, expiring in minutes to hours, not months.
- Scope the Snowflake role to least privilege. Its own role,
read_onlywhere you can, semantic views instead of raw tables. Grant to the question, not to the whole schema. - Enforce a Snowflake network policy on the token's user, so a stolen credential is dead weight off the allowed network.
- Enforce MFA and require it through an authentication policy. Single factor accounts with no MFA turned on were the whole reason behind UNC5537. Snowflake now enforces MFA for human users by default. Pin it with an authentication policy, so it can't quietly get switched off. Keep agent identities on network restricted PATs, not a bare password.
- Turn on
read_onlyon the SQL execution tool unless a tool truly needs to write. - Log and audit each tool call with enough detail to answer "which agent read which rows, when, under whose authority."
These are standard least privilege controls, applied to a new execution surface. Nothing exotic here. One caveat: treat this as an engineering threat model, not full security advice. Your data classification, compliance rules, and identity provider will each add their own line items.
Govern the data plane, not just the prompt
Each control above bounds what the agent will do. The stronger move is to also bound what the agent can reach. Down at the data layer, before a prompt ever runs.
That's the angle we build for at DataShield. It works alongside Snowflake and Horizon, not instead of them. It is definitely not a prompt proxy. Two ideas do most of the work. First, tokenize sensitive fields at ingest. A hijacked agent that somehow wins the RBAC lottery finds tokens where raw PII used to live. The reachable data collapses to something non-sensitive. Second, authorize per tool call. DataShield issues scope-ceiling MCP tool tokens. It caps each single call at that ceiling, through a per-call dispatch pipeline. It supports on-behalf-of delegation. It keeps Snowflake credentials in an encrypted connection vault, not a shared PAT. Revoke an agent mid-session, and it dies on its next call. Not whenever a token happens to lapse.
Then make it provable. A tamper-evident audit chain seals each call. You can verify it after the fact. Native RBAC tells you what a role could do. A provable chain tells you what an agent really did. If you want the full picture, the architecture and security pages go deeper than one blog section should.
Watch: related explainers
Snowflake agent workflows in practice, plus the identity and MCP risks to lock down.
Frequently asked questions
How do you secure a Snowflake MCP server so an AI agent isn't overprivileged?
Cap access in three layers. Give the server its own, read only, least privilege Snowflake role that sees semantic views, not raw tables. Bind each MCP token to that one server with RFC 8707 audience checks. Keep it short lived, and refuse token passthrough. Enforce a network policy on the token's user. Turn on read_only on the SQL execution tool, and log each call. The agent inherits the grants of the role that connects it, so a narrower role cuts the blast radius.
Why is a natural-language question a bigger risk than a normal SQL query?
A human analyst often bounded a query with LIMIT and WHERE clauses, out of habit. A natural language tool call has no such reflex. So one harmless prompt can pull large amounts of regulated data, such as PII or PHI, into the model's context. That happens in a single call. The call runs under the RBAC of the role that's logged in. So the agent can retrieve anything that role can see.
What does the MCP authorization spec require for token handling?
Per the 2025-11-25 version, MCP servers act as OAuth 2.1 resource servers. They MUST check that tokens were issued just for them (RFC 8707 audience binding). Clients MUST send the resource parameter and use PKCE with S256. Tokens go in the Authorization: Bearer header on each request, and MUST NOT appear in the query string. Token passthrough to upstream APIs is forbidden, and servers SHOULD issue short lived tokens.
Are Snowflake Programmatic Access Tokens safe to use for MCP?
They can be, if you set them up tightly. A PAT can be restricted to a single role. Its role sets what it can reach. The user must sit under a network policy. The risk is the setup. A PAT defaults to a 15-day expiry and can be stretched to 365. So teams leave DAYS_TO_EXPIRY long, use a role that's too broad, or share one token across many agents. Keep expiry short, keep the role narrow, and avoid shared service accounts. Snowflake's docs also note a per-user cap of 15 PATs.
Which OWASP agentic categories apply to an overprivileged Snowflake MCP agent?
The OWASP Top 10 for Agentic Applications came out on December 9, 2025. The direct hits here are ASI03 Identity and Privilege Abuse and ASI02 Tool Misuse and Exploitation. Both are often triggered by ASI01 Agent Goal Hijack, ranked number one, with EchoLeak as its cited example. A broadly scoped role lets a hijacked agent turn a harmless request into unapproved bulk data access.