On August 3, 2026, a short entry landed in the Azure Databricks release notes. No keynote, no blog post with a hero image, no banner in the workspace. Just this:
MANAGEno longer requiresUSE CATALOGorUSE SCHEMAon the same object.
Reads like cleanup. The kind of line you skim past on your way to the connector announcements.
Then, a couple of paragraphs down, the same release note says something that should make you open a SQL editor:
If you granted
MANAGEbroadly without also granting the corresponding usage privileges, those grants are now active.
Not "will become active after you migrate." Not "opt in from the Previews page." Active. Grants that did nothing on August 2 do something on August 3, and nobody had to run a single GRANT statement to make that happen.
If your metastore has been around for more than a year, there is a real chance you have some of these.
What MANAGE actually gives someone
MANAGE is the privilege people reach for when they want a team to administer an object without owning it. A MANAGE holder can grant and revoke privileges on that object, transfer ownership, and generally behave like the owner for access control purposes. It is the closest thing Unity Catalog has to delegated admin.
The old rule was that MANAGE on a catalog or schema only took effect if the principal also held usage privileges on that same object. So this:
GRANT MANAGE ON CATALOG prod TO `platform_engineering`;
did nothing by itself. Without USE CATALOG prod, it was a row in a metadata table and not much else.
The new rule, straight from the docs:
-
MANAGEon a catalog requires no usage privileges. -
MANAGEon a schema requiresUSE CATALOGon the parent catalog, but no longerUSE SCHEMAon the schema itself. -
MANAGEon a table, view, volume, or function is unchanged. It still needsUSE CATALOGplusUSE SCHEMAon the parents.
The reasoning is sound. An owner never needed USE CATALOG on their own object, so making MANAGE behave the same way removes a genuine inconsistency. Plenty of engineers granted MANAGE, watched nothing happen, and spent an afternoon figuring out why.
The problem is the direction of the fix. The old inconsistency failed closed. The new consistency fails open, and it applies retroactively to every grant already sitting in your metastore.
Why you probably have dormant grants
Three patterns show up over and over.
Bootstrap scripts. Somebody wrote a workspace setup script in 2024 that granted MANAGE to a platform group across every catalog, because that felt like the safe default for an admin group. Usage privileges were handled separately, per environment, by a different script.
Terraform drift. A module grants MANAGE at catalog level to a governance group and scopes USE CATALOG per environment. Dev and staging got both. Production got the MANAGE and, somewhere in a refactor, lost the usage grant. Nobody noticed, because the effective permission was zero.
Incident response. Someone got MANAGE at 3am to unblock a broken pipeline. During cleanup the next week, the team revoked USE CATALOG. That felt like closing the door. It closed nothing. It just made the MANAGE grant invisible until a platform change woke it up.
Find them
Two queries. Run both as a metastore admin, because system.information_schema filters rows to what the caller is allowed to see, and there is a documented quirk where a user holding MANAGE cannot view all grants through the information schema at all. If you hand this to a team lead and call it an audit, the audit will lie to you by omission.
First, every MANAGE grant on catalogs and schemas:
SELECT
'CATALOG' AS securable_type,
catalog_name AS securable,
grantee,
inherited_from
FROM system.information_schema.catalog_privileges
WHERE privilege_type = 'MANAGE'
UNION ALL
SELECT
'SCHEMA',
catalog_name || '.' || schema_name,
grantee,
inherited_from
FROM system.information_schema.schema_privileges
WHERE privilege_type = 'MANAGE'
ORDER BY securable_type, securable, grantee;
That gives you the population. The interesting subset is the grants that were dormant, which means a catalog-level MANAGE with no matching USE CATALOG for the same principal:
WITH manage_on_catalog AS (
SELECT catalog_name, grantee
FROM system.information_schema.catalog_privileges
WHERE privilege_type = 'MANAGE'
),
usage_on_catalog AS (
SELECT catalog_name, grantee
FROM system.information_schema.catalog_privileges
WHERE privilege_type = 'USE CATALOG'
)
SELECT
m.catalog_name,
m.grantee,
'newly_effective' AS status
FROM manage_on_catalog m
LEFT ANTI JOIN usage_on_catalog u
ON m.catalog_name = u.catalog_name
AND m.grantee = u.grantee;
One honest caveat: this compares principals literally. If the grantee is a group whose members pick up USE CATALOG through another group, the row is a false positive. Treat the output as a shortlist for human review, not a verdict. In a metastore with a few dozen catalogs it is usually a handful of rows, which is exactly the size where a human should look at each one.
Databricks shipped the flashlight a week later
On August 10, the READ METADATA privilege went generally available in Unity Catalog. It gives read-only visibility into the same metadata available to an object's owner or a MANAGE holder, including the things BROWSE hides: privilege grants, row filters, column masks, and ABAC policies.
This matters more than it sounds. Before READ METADATA, to inspect who could change permissions on a catalog, you had to hold MANAGE or own it. The audit role was itself a privilege escalation. You could not look without also being able to touch.
-- Read-only visibility into grants, masks, filters and ABAC policies.
-- No SELECT on the data. No ability to change a single grant.
GRANT READ METADATA ON CATALOG prod TO `data_governance_auditors`;
-- Compare with what most teams do today, which also hands
-- the auditors the power to rewrite everything they audit:
-- GRANT MANAGE ON CATALOG prod TO `data_governance_auditors`;
If you run a security or platform function, this is a straight swap worth making this week. It is the rare governance feature that reduces someone's permissions and makes their job easier at the same time.
The bigger shift underneath all of this
August also brought two things that look unrelated until you line them up:
Tag automations (Beta, August 7). A rule that assigns or removes governed tags on Unity Catalog tables and volumes matching conditions you define. You can describe the rule to Genie in natural language or build it by hand. Saving one starts a dry run that records what it would have matched, without touching a tag.
ABAC GRANT policies expanded (Beta, August 11). These dynamically grant Unity Catalog privileges to securables whose governed tags match a condition. They used to cover models only. They now cover model services, model provider services, MCP services, agent services, and skills.
Stack those with the MANAGE change and a pattern shows up. Access in Unity Catalog is turning from an enumerated list into a computed result. A rule decides the tag. A policy decides the grant from the tag. A platform semantics change decides how the whole thing evaluates.
That is genuinely better at scale. Nobody wants to maintain grants by hand across ten thousand tables and a growing pile of agent services. But it changes what "reviewing permissions" means. A SHOW GRANTS output is a snapshot of a computation, not a source of truth you can diff against a spreadsheet.
Which is why I now run something like this on a schedule instead of on demand:
from databricks.sdk import WorkspaceClient
from databricks.sdk.service.catalog import SecurableType
w = WorkspaceClient()
DELEGATED = {"MANAGE", "ALL_PRIVILEGES"}
for catalog in w.catalogs.list():
grants = w.grants.get(
securable_type=SecurableType.CATALOG,
full_name=catalog.name,
)
for assignment in grants.privilege_assignments or []:
held = {p.privilege.value for p in assignment.privileges or []}
delegated = held & DELEGATED
if not delegated:
continue
print(
f"{catalog.name:30} {assignment.principal:35} "
f"{sorted(delegated)} use_catalog={'USE_CATALOG' in held}"
)
w.grants.get returns the explicit grants on that securable, not the inherited ones. That is deliberate here: you are looking for grants a human typed, not for effective permissions. If you want the effective view, w.grants.get_effective is the call, and it is the one you want when the question is "what can this principal actually do right now."
Run it as a weekly job, write the output to a Delta table, and diff week over week. A governance control you only run after an incident is not a control.
What I would do before Friday
Run both queries as a metastore admin. For every catalog-level MANAGE with no matching usage grant, find a human who will say out loud that the group in question should be able to rewrite grants on that catalog. If nobody will say it, revoke the MANAGE. Then swap your audit groups from MANAGE to READ METADATA, and put the SDK sweep on a schedule so the next semantics change shows up as a diff instead of a surprise.
And before you enable tag automations anywhere near production, use the dry run. It is the only cheap moment in that feature's lifecycle.
The part that actually bothers me
The MANAGE change is correct. Consistency with ownership is the right model.
What bothers me is the delivery. Look at the rest of the August release notes. Connectors shipped in Beta. ABAC GRANT policy expansion shipped in Beta. Tag automations shipped in Beta, with a dry run, behind a Previews toggle. Serverless compute access control went GA with an explicit note that everyone keeps Can Use by default so nothing breaks.
The one change that quietly widens effective permissions across every metastore shipped straight to everyone, immediately, as a bullet point.
This is how managed platforms work now, and it is not unique to Databricks. Fabric workspace roles and Purview policies get the same treatment. Your access model is not just what you wrote. It is what you wrote plus how the platform currently interprets it, and the second half updates without asking.
So here is the thing I have not solved: how do you detect a permission change that arrives as a semantics update rather than as a grant? Scheduled diffs of effective permissions catch it, but only after it has already happened. If you have found something that catches it before, I would like to know what it is.
Top comments (0)