Bolt-generated apps frequently include a Supabase key in the exported code. Whether that is a problem depends on which key it is and whether Row Level Security is configured. The anon key is meant to be public but is only safe behind RLS; the service_role key must never be exposed and needs immediate rotation if it was.
Why it's a problem
Without Row Level Security, a public anon key gives anyone who reads your bundle or repo full read and write access to your database. If the exposed key is the service_role key, it is worse: it bypasses RLS entirely and grants complete admin control. Either way, a Bolt app pushed to a public repo has its keys scraped quickly.
How to fix it, in order
- 1Identify the key. Determine whether it is the public anon key or the secret service_role key. If it is the service_role key, rotate it in Supabase immediately and remove it from client code.
- 2Enable Row Level Security. Turn on RLS for every table with policies that scope access to the row owner. The anon key is only safe once this is done.
- 3Move keys to environment variables. Keep the anon key in an environment variable and any secret key strictly server-side.
- 4Test access. Using the public key, try to read a table you should not have access to. If it returns data, your policies are not restricting anything yet.
Why Bolt does this
Bolt scaffolds a working full-stack app fast, and wiring Supabase with the key inline is the quickest path to a running preview. It does not configure Row Level Security, because that is a manual step in the Supabase dashboard the generated code cannot perform.
Stop it happening again
Set up Row Level Security the moment you connect Supabase, keep the service_role key server-side only, and scan the exported app for inline secrets before you push it.
The quick fix
- Identify anon key (needs RLS) vs service_role key (rotate now).
- Enable Row Level Security on every table.
- Move keys to environment variables; keep secret keys server-side.
- Test that your policies actually restrict access.