Illustrative scenario. The table, tenant IDs and policies below are fabricated. This is an audit method, not a claim about any live Supabase project.
The intended boundary
A workspace application stores invoices under tenant_id. Users may belong to more than one workspace, but should see only invoices belonging to a tenant where they have an active membership. The application filters invoice queries in its frontend.
A frontend filter is useful for presentation but does not enforce the database boundary. The review asks whether every exposed data path applies the same ownership rule when a client queries the table directly.
What a scoped review would inspect
- RLS coverage: confirm the table has row level security enabled and that the roles exposed to browser clients have only intended grants.
- SELECT policy: inspect whether the policy checks the current user’s membership for the invoice’s
tenant_id, including membership status and tenant-scoped role where relevant. - Write policies: inspect
WITH CHECKfor INSERT and UPDATE so a user cannot move a row into a tenant they do not control. - Privileged paths: trace Edge Functions or backend code using service-role or secret keys. Such paths may bypass RLS and need their own authorization checks.
- Storage and related tables: check whether invoice attachments and child records use compatible tenant boundaries.
Synthetic observation
Imagine that the SELECT policy checks only auth.uid() IS NOT NULL. It proves that a request is authenticated, not that the requester belongs to the invoice’s tenant. A tenant A user querying a known tenant B invoice ID could receive that row if the table grants SELECT.
Policy text and grants alone may justify a high-priority review finding. A runtime access claim requires a controlled two-tenant test or equivalent existing evidence. A read-only audit should not silently create production test users or records.
Recommendation and verification
Express the intended membership check in the policy and test both positive and negative cases with separate tenant identities. Include direct table reads, joins, inserts and updates; also test the application’s privileged endpoints. Confirm that tenant A cannot see tenant B’s invoice or attachment even when an ID is known.
Document any remaining uncertainty: a policy may look correct while a service-role endpoint still exposes data. The report should distinguish verified behavior from code-level risk and explain which access paths were covered.
Why this finding matters
Tenant isolation is a business boundary, not a cosmetic query condition. A useful report names the affected objects, the policy or endpoint, the plausible cross-tenant path, confidence in the evidence and the test needed before release.