Who can actually read your data
In an app built with Lovable, Bolt or v0 on top of Supabase, the rows are in the database and the rules about who may read them usually are not. A signed-in user can read every other user's records. Nothing on screen says so: the interface shows only what you told it to show, while the database hands over whatever it is asked for.
How common this is has been measured. In May 2025, security researcher Matt Palmer published CVE-2025-48757: scanning 1645 applications built on Lovable, he found 303 endpoints across 170 projects — roughly a tenth of them — with inadequate row level security. What was exposed included personal data, payment information and API keys. The issue was rated 9.3 out of 10 for severity.
The mechanism is simple. Supabase hands the database to the browser: your frontend talks to it directly using a key that sits in the page source, visible to anyone. That is by design. The only thing standing between a visitor and an entire table is row level security, a set of rules enforced by the database itself. With no rules in place, the key from your own frontend is enough to download the table.
First check: which tables have no RLS at all. In the Supabase dashboard, open the Table Editor — tables without row level security are marked. Faster and more precise is a query in the SQL Editor: select relname, relrowsecurity from pg_class where relnamespace = 'public'::regnamespace and relkind = 'r'. Anything showing false in the second column is open in full.
Second check: the policies on tables where RLS is on. The flag by itself means nothing. Look at the contents of pg_policies and read the conditions. A policy of the form using (true) permits everything and is equivalent to having RLS switched off — these tend to appear when a model is asked to fix a permission error. A working condition compares the current user against the row, usually auth.uid() = user_id.
Note separately any table where RLS is enabled and no policy exists. That is not a hole: the database will refuse access to everyone. But if your app still reads from that table, it is reaching it with a service key that bypasses the rules, and the thing to check is wherever that key is kept.
Third check: from the outside, not from the dashboard. Take the public project key out of your own frontend and call the Supabase REST endpoint directly, with no account signed in, asking for every row of a table that matters. The tool does not matter: curl, Postman, the Network tab. If rows come back, they are public right now. Then repeat it with a token for a second test user and see whether they can read the first user's rows.
Fourth check: files and keys. Under Storage, look at which buckets are marked public — a public bucket is a link open to anyone who guesses or finds it. In the summer of 2025 the Tea Dating Advice app lost roughly 72,000 images this way, thousands of them selfies holding identity documents, all sitting in unprotected storage. Then open your site's built js and search it for the word service_role: the service key ignores every policy and has no business being in a browser.
If a check turns something up, the order of the work matters more than the speed of it. Make sure you have a fresh database backup before you touch anything. Change access rules one table at a time, confirming after each that the app still works: a policy written in haste across every table at once usually breaks sign-in or breaks a listing, and then it gets dropped entirely and you are back where you started.
If a service key was ever exposed, rotating it is part of the fix, not a task for later. The old key stays valid until it is replaced, and for all that time it keeps working for whoever took it. The same goes for any third-party keys found in the bundle.
One last thing: for as long as the rules were missing, you do not know whether anyone read someone else's rows. Supabase keeps API logs for a limited window, but they are worth reading — if only to know whether you are fixing something for the future or handling an incident your users will need to be told about.
The checks themselves take an evening and you can do them yourself. What comes after is the less pleasant part: a rule per table, separate rules for writes and deletes, keys and buckets, and then all of it again from the outside with someone else's eyes, because access holes are almost never where they were looked for.