medium severity · fix guide

How to Fix a Publicly Readable Supabase Database (RLS)

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.

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.

The steps

  1. Decide whether the spot the scan shows is meant to be readable without a login
  2. 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
  3. If it is, keep it public on purpose, and record that decision so a review does not reopen it
  4. Do not switch on a restrictive policy for a table your public pages read without a replacement read policy, or those pages stop working
  5. Re-check that an anonymous request returns what you decided it should

Fix it with your AI coding tool

Pick your tool and paste the instruction. It is written to make the goal above true, and to never print any secret values back to you.

Paste this to Any AI tool:
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 it worked

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.

Check your app for this issue

Free, read-only. See whether the issue is detected, then rescan after your fix: the recheck says whether it is still detected.