Supabase vs Firebase security
Supabase and Firebase are the two databases most AI-built apps reach for, and they fail the same way: both are readable until you write the rules that lock them down. They just use different mechanisms. Here is how each controls access, the mistake that leaves each one open, and a live check for your app.
Scan your app
What it means
Anyone can read this table without logging in. That can be deliberate, such as reference data or a public directory, or a missing access policy; only you can say which. xlogs read one row's column names and kept none of its values.
Why AI tools cause it
Supabase only limits who can read a table once you turn on Row Level Security (RLS) and write access rules for it. An AI tool can build a working app without doing that, and a table without RLS, or with a policy that lets everyone read, answers anonymous requests.
How xlogs checks it
xlogs finds your public Supabase URL and anon key in your app (the same ones your frontend uses), asks the database for its table list, reads one row from each listed table as an anonymous user, and flags any that return rows. Hosted Supabase refuses that list to public keys, so on a hosted project the result says the tables could not be checked. Read-only: it never writes or deletes.
How each one controls access
Supabase is Postgres. You protect a table by turning on Row Level Security and writing policies that say who can read or change which rows. Until you do, the table is readable by anyone with the public key your app ships.
Firebase protects data with Security Rules. You write rules per collection that say who can read or write. New projects often start in test mode, where the rule effectively allows anyone, and that setting quietly ships to production.
The mistake that leaves each one open
On Supabase, it is leaving Row Level Security off. On Firebase, it is leaving the rules in test mode (allow read, write: if true). Different words, same result: a stranger with your public config can read your data.
Neither tool is less safe than the other in principle. The risk is the same human step, writing the access rules, being skipped because the app works fine without it.
| Supabase | Firebase | |
|---|---|---|
| Data model | Postgres (SQL tables) | Firestore / Realtime DB (documents) |
| Access control | Row Level Security policies, per table | Security Rules, per collection or path |
| The common mistake | RLS left off, table world-readable | Rules left in test mode (if true) |
| How to check it | Send an anonymous read; if rows come back, it is open | Review your Security Rules in the Firebase console or emulator |
| Can xlogs verify it live? | Partly: one anonymous read of each table the database lists; hosted Supabase refuses that list, and the result says so | No; xlogs checks your keys, headers and source, but Firebase rules are checked in Firebase |
How to fix it
The goal: Row Level Security is enabled on every table, and each table returns rows only to the users it is meant for: a private table answers no anonymous request, and a table that is public on purpose has a read policy that says so.
- Decide whether the affected spot is meant to be readable without a login
- If it is not, enable Row Level Security (RLS) on the affected spot and add a policy so only the users allowed to see a row can read it
- If it is, keep it public on purpose, and record that decision so a review does not reopen it
- Do not switch on a restrictive policy for a table your public pages read without a replacement read policy, or those pages stop working
- Re-check that an anonymous request returns what you decided it should
In my app (the spot the scan shows): anyone can read this table; confirm that is deliberate. Please make this true: Row Level Security is enabled on every table, and each table returns rows only to the users it is meant for: a private table answers no anonymous request, and a table that is public on purpose has a read policy that says so. Steps: Decide whether the spot the scan shows is meant to be readable without a login; If it is not, enable Row Level Security (RLS) on the spot the scan shows and add a policy so only the users allowed to see a row can read it; If it is, keep it public on purpose, and record that decision so a review does not reopen it; Do not switch on a restrictive policy for a table your public pages read without a replacement read policy, or those pages stop working; Re-check that an anonymous request returns what you decided it should. Then tell me exactly what you changed, and do not print any secret values back to me or write one into a commit message, a pull request description or a log.
Then verify: After you decide and deploy, xlogs repeats the same anonymous read of each table the database lists and reports what comes back: a table you made private should no longer return rows, and one you keep public still will. If the table list is refused, it says the tables could not be checked.
Full step-by-step fix guide, with a copy-paste block for each AI tool →
Common questions
Is Supabase or Firebase more secure?
Neither is inherently safer. Both are open until you write access rules (Supabase RLS policies, Firebase Security Rules), and both let you build a fully locked-down app. The real risk is skipping that step, which is equally easy on either.
Can xlogs check my Firebase rules?
Not directly. xlogs scans your live app for exposed keys, missing headers, and source exposure regardless of your backend, and it tests Supabase tables with an anonymous read. Firebase Security Rules are evaluated inside Firebase (the console or the local emulator), so check them there.
