Category 2 of 10
Access control and data isolation
Every read and write is scoped to the user or tenant that owns the data, enforced where the data lives.
v1.0 · verified on 2026-09-21
Isolation is enforced where the data lives. Every item here is run as a second user, because the only proof that a policy works is a foreign read that returns nothing.
Every table exposed to the client has row-level security enabled
automated Query the database catalog for tables in exposed schemas and their RLS flag (Supabase, Postgres) or list collections against rules (Firebase).
Every exposed table reports RLS enabled; the list of exemptions is empty or each exemption is a public read-only table named in the release notes.
Policies deny cross-tenant reads and writes when tested as another user
automated For every table or collection, sign in as user A, create a row, then as user B attempt select, update and delete on it through the client API.
User B receives zero rows on select and a permission error on update and delete, for every table.
Object access checks ownership, not only login
automated For each endpoint or action that takes an id, call it as a logged-in user with an id owned by another user.
Every id-bearing endpoint returns 403 or 404 for a foreign id; none returns the object.
Admin functions are verified on the server
automated Call every admin route and admin server action as a regular user, with and without an admin flag set in the client state or query string.
Every admin route and action rejects the regular user regardless of client-side flags.
The client receives only the fields it renders
manual Inspect API responses and the server-component payload for the five most sensitive screens and list every field returned.
No password hash, token, internal note, other user's email or billing detail appears in any inspected payload.
Firebase rules are out of test mode and covered by rules tests
tool Read the deployed Firestore, Realtime Database and Storage rules; run the rules unit tests in the emulator.
No rule grants read or write to all users without a condition; the rules test suite exists and passes.
Dots: Starter, Growth, Scale. Compare plan limits.
Failure patterns these items catch
- criticalRow-level security off on a new table
A table created by a migration or SQL has no row-level security, so the anonymous key can read and write every row through the public API.
- criticalPolicy that allows everything
Row-level security is enabled but the policy condition is true for everyone, so isolation exists in name only.
- criticalList endpoint returns other tenants' rows
A list or search endpoint filters by the wrong column or none, so a user sees records belonging to other accounts.
- criticalObject fetched by id without an ownership check
An endpoint checks that the caller is logged in, then returns whatever id was requested.
- criticalAdmin gate enforced only in the UI
The admin page hides its buttons from ordinary users, but the underlying route or action accepts calls from anyone logged in.
- criticalRole or flag read from the request
The server decides what a user may do from a role, plan or isAdmin value that arrived in the request body, query string or client state.
- criticalFirebase rules still in test mode
The database or storage rules allow any client to read and write because the permissive development rules were never replaced.
- highWhole records passed to the client
The server sends the full database row to the browser and the UI shows a few fields; the rest, including other people's data, is in the payload.
Ask which plan runs these items
Email with your team size, cadence and stacks. We reply within 24 hours on business days.