
To check that a Supabase app protects user data, confirm that every table the API can reach has row level security (RLS) turned on, that each policy limits rows to the signed-in user or their team, that new tables have deliberate grants, and that no secret key ships in the app. Then test it by querying as a stranger.
Picture a founder who built a client portal with an AI app builder on top of Supabase. Sign-up works, invoices show up, the demo goes well. Before launch, a friend opens the browser's developer tools, copies the project URL and the public key from the page, and asks the database for every row in the invoices table. Every customer's invoices come back. Nothing was hacked; the table simply had no rule saying who may read which row.
What is row level security in Supabase?
Row level security (RLS) is a Postgres feature that decides, row by row, which records a database role may read or change. In Supabase it is the main thing standing between your public API key and your users' data.
A Supabase app usually talks to the database straight from the browser or mobile app through the Data API, using a publishable key (the older name is the anon key). Supabase's API keys guide is clear that "Anyone can read it, so it only reaches what Row Level Security allows." Its RLS guide is blunter: "A table in an exposed schema without RLS is readable and writable by any role with a grant on it. Enable RLS on every table in an exposed schema."
A policy is a rule attached to a table, such as "a user may read an invoice only if the invoice's customer id matches their own user id." Once RLS is on, Supabase says "no data is accessible through the API when using a publishable key, until you create policies."
What changed in Supabase on 30 October 2026?
Supabase announced in April 2026 that, from 30 October 2026, new tables created in the public schema of existing projects are no longer exposed to the Data API automatically. Each new table needs an explicit Postgres grant before the API can see it. Existing tables keep their current grants.
The changelog entry says that "new tables you create in public schema require an explicit opt-in (via a Postgres grant) before the Data API can see them," and that "Existing tables are not affected in your project, they keep their current grants and stay reachable." Apps that only use a direct database connection, through an ORM or a server with a connection string, are not affected.

What this means in practice
A new table that "doesn't work". If the app gets a "permission denied for table" error on a table created after the change, the table is missing a grant, not a policy.
Grants and RLS do different jobs. A grant decides whether a role can touch the table at all. RLS decides which rows that role sees. You need both: a grant so the app can reach the table, and policies so each user reaches only their own rows.
Don't fix the error by granting everything. Grant only the actions each role needs. A table that signed-out visitors never read should not be granted to the anon role.
The change makes exposure a decision instead of a default. It does not make old tables safe, and it does not write policies for you.
Why do AI-built Supabase apps leak data?
Most leaks come from tables that were created without RLS or with policies that allow everyone, because the app still works in a demo either way. AI app builders produce working screens quickly, and a missing rule doesn't show up until someone queries the API directly.
There is a public record of this pattern. CVE-2025-48757, published in the US National Vulnerability Database in May 2025, describes "an insufficient database Row-Level Security policy in Lovable through 2025-04-15" that allowed unauthenticated attackers "to read or write to arbitrary database tables of generated sites." The record notes that Lovable disputes it, on the grounds that each customer is responsible for protecting their own application's data. That dispute is the practical point: whoever ships the app owns the policies.
We covered the wider set of launch problems in what breaks when an AI-built app gets real users. RLS is usually the first one we check.
How do you check RLS before launch?
Run Supabase's Security Advisor, read every policy against what the table holds, look for secret keys in the client, and then try to read and write data as a signed-out stranger and as a second user. If any of those attempts succeeds where it shouldn't, you are not ready.
The launch check
Run the Security Advisor. Supabase's advisors flag tables with RLS disabled in the public schema as an error ("Table publicly accessible"), along with policies that exist on tables where RLS is off and tables with RLS on but no policies.
List every exposed table. For each one, note what it holds and who should see it: everyone, signed-in users, the owner only, or a team.
Read each policy. Check that it filters by the user's id or team membership, and that it covers each action (read, insert, update, delete) the app uses.
Check the grants. For tables created after 30 October, confirm the grants match what each role needs, and nothing more.
Search the client for secret keys. Supabase's API keys guide warns that "A secret key bypasses every Row Level Security policy you have. Never put one in a browser, a shipped application, or source control." Search the built app bundle and the repository, not just the source files.
Test as a stranger. With only the project URL and the publishable key, try to read and write each table. Every attempt on private data should return nothing or an error.
Test as the wrong user. Sign in as user A and try to read or change user B's rows by changing ids in requests.
Check stored files too. If the app keeps uploads such as invoices or ID documents in Supabase Storage, run the same stranger and wrong-user tests on reading and uploading files.
What are the most common RLS policy mistakes?
The common mistakes are policies that allow every row, policies that trust data the user can edit, and checks that cover reading but not writing. Each one looks fine in a demo and fails with a curious user.

"Allow all" policies. A policy whose condition is simply true, often added to make an error go away, gives every signed-in user (or everyone) every row.
Trusting editable fields. A policy that checks a role or team stored in a profile row the user can update lets users promote themselves. Keep roles in a table users can't write to.
Read rules without write rules. A user who can only read their own rows may still be able to insert rows for someone else, or update the owner field, if insert and update aren't checked.
Sensitive columns in a public table. A profiles table that is readable by everyone may also hold emails or phone numbers. Move those columns to a private table, or use Postgres column-level privileges, which grant access to specific columns rather than the whole table.
Slow policies. Policies run for every candidate row. Supabase recommends wrapping auth functions in a select so the result is cached per statement, and adding "an index on every column your policies filter on."
How we approach it at Vizio AI
When we take over an app built on Supabase, the data access review comes before any new feature. We list every table and storage bucket, write down who should see what, and compare that with the policies and grants that actually exist.
Then we test as a stranger and as a second user, fix the policies and grants, move secrets server-side, and re-run the same tests so the fix can be checked again after every release. The approach is the same as in our post on whether to fix or rebuild someone else's app: find out what is really there before deciding what to change. If your app is close to launch and you aren't sure the data is protected, see how our Venture Studio works with founders on finishing a build.
Sources
Supabase Changelog, Breaking Change: Tables not exposed to Data and GraphQL API automatically (28 April 2026): https://supabase.com/changelog/45329
Supabase Docs, Row Level Security: https://supabase.com/docs/guides/database/postgres/row-level-security
Supabase Docs, API keys: https://supabase.com/docs/guides/api/api-keys
Supabase Docs, Advisors: https://supabase.com/docs/guides/database/database-advisors
Supabase Docs, Column Level Security: https://supabase.com/docs/guides/database/postgres/column-level-security
National Vulnerability Database, CVE-2025-48757: https://nvd.nist.gov/vuln/detail/CVE-2025-48757
Vizio AI, Your AI-Built App Works in the Demo. Here's What Breaks With Real Users: https://www.vizio.ai/resources/blog/ai-built-app-what-breaks-with-real-users
Vizio AI, Fix It or Rebuild It? How We Decide When We Take Over Someone Else's App: https://www.vizio.ai/resources/blog/take-over-existing-app
Vizio AI, Venture Studio: https://www.vizio.ai/studios/venture-studio
Vizio AI, Finish your build: https://www.vizio.ai/finish-your-build












