BUILD OS · AUTHORIZATION
Supabase users can access other users’ data
Short answer
Authentication proves which user made a request; it does not prove that the user owns the requested row. Check row level security and every server-side read and write with two separate accounts, including requests that substitute another user’s record ID.
Symptoms
- Changing an ID in a URL or request returns another account’s record.
- A hidden button protects a page, but a direct API request still succeeds.
- A server route trusts a user ID supplied by the browser.
Why this happens
Data access is safe only when authorization is enforced where the resource is read or mutated. UI visibility and an active session do not constrain a database query by themselves.
Most likely causes
- RLS is disabled on a browser-reachable table.
- A policy checks only that a user is signed in, not ownership or tenant membership.
- A server query uses a client-supplied owner ID.
- An elevated service key bypasses the policy without a separate authorization check.
How to diagnose it
- Create two ordinary test accounts with separate records.
- Try reads, updates and deletes across the two accounts through the actual app and API.
- Review RLS state and each policy in the deployed database.
- Trace every privileged server query to an identity and ownership check.
Fix
- Enable RLS on exposed tables and write least-privilege ownership or tenant policies.
- Derive identity from the verified session, not a form field.
- Keep elevated keys server-only and authorize each operation before using them.
- Add cross-account regression checks for sensitive resources.
Verify the fix
Do not close the issue until these checks pass in the environment that matters:
- Account A can access its own permitted records.
- Account A is denied account B’s records for read, update and delete.
- Signed-out and expired-session requests are denied.
- Tests run against the deployed policy state or a production-like database.
Related Ship Passport checks
Build School’s production-readiness standard marks this area as proven only with evidence from these checks (it is Build School’s own standard, not an external certification):
- criticalUser A cannot access user B’s data
- criticalThe server derives identity from the session
- criticalRLS is enabled and tested on every exposed table
- criticalThe service-role key stays server-side
Common false fix
Hiding links, adding a client-side ownership check, or checking only that a session exists does not protect direct requests or database access.
Documented evidence
DocumentéUne session répond à « qui es-tu ? » ; l’autorisation répond à « peux-tu accéder à cette ressource ? ».
Source note: authentification-nest-pas-autorisation · Updated 2026-09-26. This is documentation provenance; it is not a claim about frequency.
Related build: atamatax
Primary references
Related pattern
Authentication is not authorization →
Build OS stage
Authorization · Explore Build OS →