Genie row-level security: how to make each person see only their own data
A Finance team asked how to stop cost-centre owners seeing each other's numbers in Genie. The answer is Unity Catalog, plus one trap: your own app or API.
A data lead preparing a Finance rollout asked a public Databricks Community thread a question that every governance team asks before Genie goes near real numbers: how do we make sure each person only sees their own data? The concrete worry was a cost-centre owner asking Genie a question and getting another team’s figures back. They sketched a plan built on role-based and attribute-based access control, and a reply corrected one step of it in a way that is worth spelling out.
We think the corrected version is the right mental model. Here is how we would explain it to a governance committee.
Genie has two credentials, and they do different jobs
This is the part that trips people up. According to the Databricks documentation, a Genie Agent (the new name for a Genie space) needs a pro or serverless SQL warehouse. When the author saves the warehouse selection, their compute credentials are embedded so that everyone using the agent can reach the warehouse. Those embedded credentials grant warehouse access only.
Data access is a separate question. The docs say data access is always evaluated using each end user’s own Unity Catalog permissions. Users need SELECT on every Unity Catalog object the agent uses, plus at least CAN VIEW or CAN RUN on the agent itself.
So the author’s credential answers “can this agent run queries at all?” and the user’s identity answers “which rows and columns does this person get?” Nobody needs to be handed a warehouse permission, and nobody inherits the author’s data access.
What happens when someone asks for data they cannot see
Per the docs, a question about data the user cannot access returns an empty response, and queries are attributed to the end user in query history and on the agent’s monitoring page.
That has two consequences for design:
- You do not build separate agents per audience for row-level rules. The docs say that to limit what each user sees within one agent, you apply row-level security to the underlying Unity Catalog tables, and row filters and column masks are enforced per user automatically, however the agent is shared. One Finance agent can serve every cost-centre owner.
- Empty is not the same as wrong. A user who sees nothing may be hitting a filter, a missing SELECT grant, or a genuinely empty result. Tell your pilot users what an empty answer can mean, or your first support tickets will be “Genie is broken”.
Put the rules in Unity Catalog, not in Genie
Genie is not where access policy lives, and that is a feature. The rules belong in Unity Catalog:
- Row filters are SQL functions evaluated at query time. Rows where the function returns false are excluded. A common shape is a mapping table of user to allowed cost centre, or a check on group membership.
- Column masks return either the real value or a masked one, for example for personal data.
- Attribute-based access control lets you attach policies to governed tags so they apply wherever the tag appears, rather than configuring each table by hand. Microsoft’s Azure Databricks documentation recommends ABAC for centralizing access control at scale, and row filters and masks when you need per-table logic or have not adopted ABAC yet. Databricks’ own governance write-up makes the related point that ABAC is a way to attach filters and masks through policy, not a replacement for them.
Group membership usually comes from your identity provider via Automatic Identity Management, so your policies are only as accurate as the groups that sync. If the Finance org chart changed last week and the groups did not, Genie will faithfully enforce last week’s org chart.
The trap: Genie behind your own app or API
This was the correction in the thread, and it is the one we would put at the top of any review. Used directly, Genie evaluates data access as the signed-in user. The moment Genie sits behind something you built, an internal portal, a bot, an orchestrator on the Conversation API, an MCP tool, the identity Unity Catalog sees depends on how that app authenticates.
Databricks’ “Access Genie everywhere” guidance describes three OAuth patterns for custom apps:
- User-to-machine: users sign in with their corporate identity and queries run with their permissions.
- Machine-to-machine: a service principal authenticates and every user gets the service principal’s access.
- On-behalf-of: the app authenticates to Databricks first, then calls Genie for each user, with that user’s data permissions applied.
The same page covers the Teams route through Copilot Studio. With end user credentials, each person signs in with their own identity and answers reflect their access. With maker-provided credentials, everyone shares one identity, and that identity’s permissions apply to all of them.
If you pick a shared service principal for convenience, row filters and masks still run, but against the service principal, so every user effectively sees what it sees. This is not a bug, it is what you configured. A forum thread about the Conversation API with external users reached the same conclusion: per-user filtering needs per-user identity passed through. For people who do not sign in to Databricks at all, Databricks supports OAuth token federation so your own identity provider’s tokens can be used.
Test it like an attacker would
Do not rely on reading the policy. Check it:
- Ask the same question as two users with different cost centres and confirm the rows differ.
- Ask as a user with no access and confirm you get an empty response rather than a leaked total.
- Open query history and confirm each query is attributed to the person who asked. If every query shows one service principal, you have found the trap before your auditors did.
- Re-run the tests whenever policies, tags or group syncs change. Databricks’ own guidance recommends impersonating group members and comparing responses.
- Check attached volumes. The Databricks write-up notes that an agent validates access to every attached volume when it loads, so a user without READ VOLUME on one cannot use that agent at all. Volumes are the smallest grantable unit, so different audiences for documents may need different volumes and different agents.
What we would not promise
Genie enforcing Unity Catalog does not make a bad data model safe. If a cost centre is missing from the mapping table, the owner sees nothing. If a derived table copies restricted rows into an unfiltered location and you attach it to the agent, Genie will answer from it. Row-level security protects the tables you applied it to, so review which tables each agent actually exposes, and keep that list short. The documented limit is 50 tables, views or metric views per agent, with five or fewer recommended.
The short version
- A Genie Agent uses an embedded credential for the warehouse and the asking user’s Unity Catalog identity for data.
- Apply row filters, column masks or ABAC policies on the tables, not in the agent.
- Users asking about data they cannot see get an empty response, so brief your pilot group.
- Genie behind your own app or API is where per-user security quietly breaks: use user-to-machine or on-behalf-of, not a shared service principal, if you need per-person filtering.
- Test with two real users and read query history to confirm who each query ran as.
If you are planning a Genie rollout and want a second pair of hands on the governance design or a readiness review before the pilot, see our Databricks Genie implementation page.
- Databricks
- AI
- Genie
- Governance