What to do right now, even if you hire nobody
You can find the most serious row level security gaps yourself in about an hour. Turn on nothing new, change no code, and simply look: which tables have policies, which keys reach the browser, and what an anonymous visitor can read. Write down every surprise, because that list is what a reviewer will want to see first.
Do these steps on a copy or with test data where you can. If something fails, record it and stop. Asking an AI assistant to patch a failing policy in the same session often produces a policy that is broader than the original.
Open the Security Advisor
In the Supabase dashboard, run the Security Advisor and save its output. It flags tables in exposed schemas without row level security and some risky function settings.
List every exposed table
Write down each table in the public schema, whether row level security is on, and how many policies it has. A table with security on and zero policies blocks everything; a table with security off allows everything.
Query as an anonymous visitor
Using only the anon key from your frontend, request each table through the REST endpoint. Anything that returns rows to a logged-out visitor should be public on purpose.
Query as the wrong customer
Sign in as one ordinary account and request rows that belong to a different account by changing an ID. Try reading, updating and deleting, because each action has its own policy.
Find the service role key
Search your frontend bundle, mobile app build and public repository for the service role key. It skips every policy, so it must live only on the server.
Check storage buckets
Open each storage bucket and confirm whether it is public. Private files need their own policies on storage objects, separate from your table policies.
How row level security works in Supabase
Row level security is a Postgres feature that Supabase relies on as its main access boundary. Your frontend talks to the database directly with a public key, so the rules attached to each table, not the screens of your app, decide what every visitor and every signed-in user can read or change.
Each request arrives with a role: anon for logged-out visitors, authenticated for signed-in users, or service_role for trusted server code. Policies use functions such as auth.uid() to compare the requester with the row. Getting this right is mostly about precision: a policy that is almost right is usually wide open in one direction.
- A USING clause decides which existing rows a user can see, update or delete.
- A WITH CHECK clause decides which new or changed rows a user is allowed to write.
- Policies are permissive by default, so two policies on the same table combine with OR, and the broader one wins.
- The service role key bypasses row level security entirely and belongs only in server code.
- Tables created through SQL or migrations stay without row level security unless the script turns it on.
Common policy mistakes in AI-built Supabase apps
The mistakes that matter most look harmless in a demo. The app works, each user sees their own dashboard, and nothing seems wrong. The gap only appears when someone sends a request the interface never makes, such as asking for another customer's rows directly or writing a field the form does not show.
If your app was generated with an AI builder, the production-readiness review for AI-built apps covers these checks together with payments and deployment, and the Lovable guide explains how that builder connects to Supabase.
- A policy that checks only that the user is signed in, so every signed-in user can read every row.
- An update policy with a USING clause but no WITH CHECK, letting a user move a row to another account.
- Role or plan information read from user metadata, which the user can edit, instead of a table only the server writes.
- Views that run with the owner's permissions and quietly return rows the underlying policies would hide.
- Database functions marked security definer that are callable from the browser and skip every policy.
- Tables added late in the build, such as audit logs or invitations, with row level security never enabled.
- Realtime subscriptions and storage buckets left out of the review because they live outside the main tables.
- Columns such as is_admin or price that a user can change because the policy covers the row but not the field.
Supabase situations, the access needed and the likely path
What a reviewer can do depends on what you can hand over. A repository alone shows the policies as written; dashboard access shows what is actually deployed, and the two often differ. Use this table to gather access before a first call, starting with any account you do not control yet.
| Situation | Access you need | Likely path |
|---|---|---|
| Only a repository | Read access to the repository, including migration files | Compare policies in migrations with the intended roles, then test them on a fresh copy |
| Live product with no documentation | Supabase project access and a list of user roles | Map tables and roles, test each policy as anon and as the wrong user, then rank findings |
| Deployment broken | Supabase project, hosting account and environment variable names | Restore a working deploy first, then review policies on a staging project |
| Previous developer still holds the accounts | Proof the company paid for the Supabase organization | Recover ownership through the provider's own process before anyone changes policies |
| Service role key found in the frontend | Supabase project admin | Rotate the key, move the calls to server functions, then retest every table |
| Policies written by an AI builder | Repository plus dashboard read access | Review each table's policies against what each role should do, and fix in small steps |
What a Supabase row level security review covers
A review from Servify Labs looks at the running app, not only the policy text. Senior engineers working with AI tools read the schema, policies, functions and the code that calls them, then try the requests a curious or hostile user would make. You receive ranked findings in writing, and the team can fix them or take over delivery.
- Each table, view and function in exposed schemas, with its policies for read, insert, update and delete.
- Tests as a logged-out visitor, as an ordinary user reaching for another user's data, and as each higher role.
- Where the service role key and other secrets are used, and whether any reach the browser.
- Storage buckets, realtime channels and database functions callable from the client.
- A written list of findings ranked by impact, with the fix for each, and an option to have the fixes done in a sprint.
- Out of scope: penetration testing of your hosting provider, legal or compliance sign-off, and any statement that the app is free of issues.
Fix the policies in place or restructure the data model
Most apps can keep their schema and fix the policies table by table. A restructure is worth it only when ownership of a row cannot be worked out from the data, for example when records have no user or team column at all. Decide with a few questions rather than a rewrite on instinct.
Can every row be tied to an owner?
If each row has a user or team column, policies can be fixed in place. If not, adding that column comes first.
Do roles live in a table only the server writes?
If roles come from editable user metadata, move them to a protected table before trusting any admin policy.
Are server tasks using the service role key?
Keep that key for background jobs and webhooks on the server, and let user-facing requests go through policies.
Is there a staging project?
Test changed policies on a copy with realistic data before applying them to production, so a too-strict rule does not lock customers out.
When Servify Labs is not a fit
Servify Labs is not the right choice for every Supabase project. If you only need a quick patch so a demo works this week, or you do not plan to keep building the app, a short freelance session or the checklist above is a better use of money. The same applies when the budget is below our sprint price.
- You want a single policy changed and nothing else reviewed.
- There is no plan to keep developing or maintaining the app after the fix.
- You need a formal compliance certificate rather than an engineering review.
Frequently asked questions
What access do you need to check our row level security?
Read access to the repository and to the Supabase project is enough to start. Admin access is only needed once fixes begin. We never ask you to paste secret values into chat or email; we work with the names of environment variables until access is granted properly.
Is Supabase's Security Advisor enough?
It is a useful first pass and worth running before every launch. It flags tables without row level security and some risky settings, but it cannot know what each of your roles is supposed to see, so it will not catch a policy that is valid but too broad.
Will you rewrite our app?
Usually not. Most row level security problems are fixed table by table in the existing schema. A larger change is suggested only when rows cannot be tied to an owner, and you see that reasoning in the written findings before any work starts.
Does a review mean the app is safe?
No review can promise that. A review tells you which risks were found, which were fixed and which remain, so you can decide what to accept. Treat the checklist on this page the same way: it is a starting point, not a completed audit.
How much does it cost?
Ongoing work runs in two-week sprints from $3,500, paid upfront per sprint, and you can pause or cancel anytime. A one-off review is quoted in a written proposal about 20 minutes after the free intro call, based on the size of the app.
How fast can you start?
After the intro call you receive a quote and written proposal within about 20 minutes, and a second call happens the next day. Work starts the day after the agreement is signed and the first sprint is paid.
Who owns the fixes and the code?
You do. The client owns the code, the designs and the infrastructure from day one, and every change is made in your repository and your Supabase project.
What happens after the policies are fixed?
You can stop there, or continue in sprints to fix other findings, add features or take over maintenance. If the app was left by another developer, see our project takeover service.
Related
“These guys stepped in, fixed the issues, improved the UI and UX, and got us launched in just two weeks.”
Want a second pair of eyes on your Supabase policies?
Book a free intro call. You get a quote and written proposal about 20 minutes after it.
Book a free intro call