Most AI app builders sit on Supabase or something shaped like it, which makes Supabase security the single most consequential topic in this whole series. It is also the most misunderstood, because Supabase inverts an assumption people carry in from older stacks: the database is reachable from the browser on purpose, the API key in your frontend is public by design, and the entire security model lives in one place. That place is row level security, and it is exactly where the 2025 research kept finding the door open.
Quick answer: Supabase’s anon key is meant to be visible; row level security policies are what protect the data behind it. AI tools leave RLS disabled, write allow-everything policies, or paste the admin service role key into client code. Run the dashboard’s security advisors, then test as a logged-out user, and write policies that deny by default.
How does Supabase security work?
Your frontend talks to the database through Supabase’s API using the anon key, which every visitor can see. That is the design, and it is fine, because the key only opens the front gate. What each request can read or write is decided per table by row level security: policies that say, in SQL, which rows this authenticated user may touch. When RLS is enabled with good policies, the public key is harmless. When RLS is off, the public key is the whole database. There is no middle setting.
What do AI tools get wrong?
Four patterns account for nearly everything. RLS disabled entirely, often because a policy error blocked a feature mid-build and turning security off made the error go away, which the AI obligingly did. Allow-all policies: RLS technically enabled with a policy of USING (true), which is the same as off while looking safer. The service role key in client code: Supabase’s admin key bypasses RLS by design, belongs only on a server, and gets pasted into frontends whenever a permissions error frustrated a prompt session. And public storage buckets holding private uploads, which is the mistake behind the era’s ugliest incident, the Tea app’s exposed verification photos. This is precisely what researchers found scanning Lovable-built apps in 2025: production apps with user data readable by anyone who looked, and the platforms have added scanners since, which help and do not substitute for policies.
How do you check your own app in ten minutes?
- Open the Supabase dashboard’s advisors (the built-in security linter) and read every warning. Tables without RLS are listed by name.
- Log out of your app, open the browser console or curl, and query your tables through the REST endpoint with only the anon key. Rows coming back means the door is open.
- Sign in as a test user and try to read another user’s rows and files by changing IDs in requests. Getting user B’s data as user A is the finding scanners miss.
- List your storage buckets and check which are public. Any bucket holding user uploads should almost certainly not be.
- Search your frontend code and bundle for the service role key. Its presence anywhere client-side is an immediate rotate-and-fix.
How do you fix policies without breaking the app?
Table by table, with a test after each. Enable RLS, then write the owner policy: users may select, insert, update, and delete rows where the user ID column equals auth.uid(). That single pattern covers most tables in most AI-built apps. Shared and public data gets deliberate read policies; admin operations move server-side where the service role key legitimately lives. Expect a few features to break as you tighten, which is the point: each break marks a place the app was relying on the door being open, and the fix belongs in the policy or a server function rather than back in the off switch. Do it on a staging copy if you have one, and take the guardrails from our production readiness guide so the tightened rules stay tested.
What about edge functions and webhooks?
The same deny-by-default thinking, one layer up. Edge functions should verify the caller’s JWT before doing anything, because an unauthenticated function with database access is an open endpoint wearing a costume. Webhook handlers (Stripe and friends) must verify signatures so outsiders cannot forge events. And functions are where service role operations belong, wrapped in your own authorization checks, since the key inside them bypasses every policy you wrote.
Frequently asked questions
Is my anon key being visible a breach?
No. The anon key is publishable by design, like a storefront address. The breach question is what the key can reach, which is entirely a function of your row level security policies. Visible key with strict policies is the intended architecture.
What is a safe default policy?
Deny by default, then owner-only access: each user reads and writes rows where the row’s user column matches auth.uid(). Add deliberate exceptions for genuinely shared or public data. If a table has RLS enabled and no policies, nothing gets through, which is the correct starting point.
Enabling RLS made my queries slow. Why?
Policies run on every row access, so a policy referencing an unindexed column turns reads into scans. Index the columns your policies filter on, usually the user ID column, and wrap function calls appropriately. Slow policies are an indexing problem, and never a reason to disable security.
How should storage bucket rules work?
Private by default, with access through policies mirroring your tables: users read their own files, plus deliberate public buckets for genuinely public assets like product images. Signed URLs handle the sharing cases. A bucket of user documents that is publicly listable is the Tea app scenario.
Is the service role key ever OK in the client?
Never. It bypasses row level security entirely, which is its job, and its job belongs on a server: edge functions, API routes, or your backend. If it has ever shipped in client code, rotate it today and assume it was copied.
My AI assistant says security is handled. Should I trust it?
Verify. The assistant is reporting that code exists, and the advisors plus a logged-out test report whether protection exists. The full pre-launch sweep in our security checklist takes an afternoon, and a professional audit takes it off your plate.