01
What Supabase does
Supabase can provide a hosted Postgres database, user authentication, file storage, APIs, and other project services. Each part has its own access rules and failure modes.
An app can look correct while still exposing the wrong rows or files. A green UI or successful test account does not prove that another user cannot access the same data. Security needs evidence from policies, server code, configuration, and tests.
02
Why AI-built apps get database security wrong
- The client is trusted with a user ID or role it can change
- RLS is disabled, missing, or enabled without useful policies
- A service-role key is placed in browser code or a public environment variable
- Storage buckets are public when files should be private
- Policies cover reads but not inserts, updates, or deletes
- Payment access is granted from a client-side flag
- A test account proves only the happy path
03
RLS explained simply
Row Level Security (RLS) is a database-level filter that decides which rows a database request may read or change. It should enforce ownership and access rules close to the data, not only in the interface.
- Write the ownership rule in plain English first
- Test anonymous, owner, non-owner, and privileged cases
- Check SELECT, INSERT, UPDATE, and DELETE separately
- Do not assume an authenticated user should see every authenticated row
- Confirm policies match the real schema and user identity
04
Tables and policies checklist
- Every table has a clear owner or access model
- Sensitive fields are not returned unnecessarily
- Foreign keys and constraints match the intended relationships
- RLS is enabled where user data needs isolation
- Policies are reviewed for each operation
- A non-owner cannot read or mutate another user’s data
- Admin/service operations run on a trusted server path
- Migrations are tracked and tested before production
05
Keys, storage, and auth
- The browser only receives values intended to be public
- The service-role key is server-only and never committed
- Secrets are not printed in logs, prompts, screenshots, or error messages
- Private buckets require an authenticated and authorized access path
- Uploads validate size, type, ownership, and lifecycle
- Signup, login, logout, reset, verification, and refresh have failure states
- Account deletion and data retention have an owner-approved plan
06
Payments and user access
Payment status should be verified through a trusted provider flow and server-side records. A button being hidden is not an access control.
- Prices and product IDs come from a trusted configuration
- Webhook signatures are verified
- Repeated events are handled safely
- Access changes after success, failure, cancellation, and refund
- The app does not trust a browser-supplied “paid” flag
- Payment and personal data are not exposed in public queries
07
Copy-paste Supabase audit prompt
Prompt 61
Audit without changing anything
Copy-paste prompt
Audit this app’s Supabase safety without printing secrets. Inspect schema references, migrations, RLS enablement and policies, client/server boundaries, storage usage, auth flows, and payment-related access. Report verified evidence, unknowns, and the safest next checks. Do not edit files, create policies, disable security, or claim the app is secure without tests.
Use this before asking an AI tool to “secure everything”.