Maple

Field Notes · May 15, 2026

Cortex Agents Will Leak Your Tenants' Data Without Row-Level Policy

Prompt injection is not the main risk. The main risk is that Snowflake Cortex Agents has no native tenant boundary, and your LLM will happily write SELECT * FROM customers WHERE 1=1.

Brian Hess published a field note this week that every mid-market SaaS architect deploying Agentforce + Snowflake should tape to their monitor: you cannot trust an LLM to enforce tenant isolation. Not through prompting, not through few-shot examples, not through RAG context. The only safe pattern is row-level security policies enforced by the database before the query executes.

This is not a theoretical concern. Hess documents a specific case where a Cortex Agent, asked "show me all customers", generated SELECT * FROM customers with no WHERE clause. The LLM correctly interpreted the natural language intent but had no mechanism to know which tenant_id the session should be scoped to. The query ran. All rows returned. Game over.

The Pattern That Works

The solution is Snowflake's SESSION_CONTEXT + row-level policies. Before you hand control to the agent, you set a session variable with the authenticated tenant_id from your application layer. Then you define a policy on every table the agent can touch:

CREATE ROW ACCESS POLICY tenant_isolation AS (tenant_id STRING)
RETURNS BOOLEAN ->
  tenant_id = CURRENT_SESSION_CONTEXT('TENANT_ID');

Apply that policy to every table, and now the agent can generate any query it wants. The database will rewrite it to append WHERE tenant_id = 'abc123' at execution time. The LLM never sees this logic, never has to reason about it, and cannot bypass it.

This is the same pattern we use at Maple when orchestrating Agentforce + Data Cloud + Snowflake stacks. Agentforce topics call Data Cloud actions, Data Cloud federates to Snowflake, and the session context is set by a pre-query hook in the Data Cloud connector. The agent instructions never mention tenant_id. The retrieval layer never filters by tenant_id. The policy is infrastructure, not prompt.

Where This Breaks Down

The failure mode is schema explosion. If you have 500 tables and you onboard a customer who needs row-level isolation on 300 of them, you are now managing 300 policies. Snowflake has no policy inheritance, no policy templates, no bulk policy operations in the UI. You script it with Terraform or dbt, and you test it in CI, or you ship a data leak.

The second failure mode is session hygiene. If your orchestration layer reuses connections (most HTTP pools do), you must explicitly unset the session context between requests. One missing UNSET and the next request inherits the previous tenant. Hess does not mention this in the post, but we have seen it bite two customers in staging.

What Agentforce Customers Should Do This Week

If you are deploying Agentforce with Snowflake or Databricks as the data layer, audit your session setup today. If you are relying on the LLM to add WHERE clauses, you are one bad retrieval away from a breach. Implement row-level policies before you go to production. If you already shipped, implement them this sprint.

The tradeoff is operational complexity (more policies, more testing, more Terraform state), but the alternative is trusting a language model to never hallucinate a security boundary. That is not a tradeoff. That is a countdown.