Skip to content

Supabase key questionIs it safe that my Supabase anon key is in my frontend code?

A scanner, a friend or a code review flagged the Supabase key in your site’s JavaScript. That key is meant to be public. What protects your data is row-level security, so that’s the part to check. Here’s how, or hand it over at a fixed price.

Short answer

Yes, if row-level security is on. Supabase calls the anon key the legacy version of the publishable key, which it says is safe to expose online, and anyone can read it in your code. Row-level security decides what that key can reach, so turn it on for every table and give each table policies. The key that must never be public is the secret or service_role key.

What to check

  1. 01

    Which key it is

    “Safe to expose online: web page, mobile or desktop app, GitHub actions, CLIs, source code.” Supabase, Understanding API keys

    Publishable keys start with sb_publishable_, and the legacy anon key is a JWT whose role is anon. Both are public-facing keys: Supabase calls anon the legacy version of publishable keys, and its docs treat browsers and apps as public. A key starting with sb_secret_, or a JWT whose role is service_role, doesn’t: treat that one as leaked.

  2. 02

    Row-level security on every table

    “Row Level Security decides what this client can reach, so enable it on every table before you deploy.” Supabase, Understanding API keys

    Without row-level security, a table in the public schema can be read and changed by anyone holding the public key, through Supabase’s API. In the dashboard, check that every table in the public schema has RLS enabled, with policies that limit each row to the people it belongs to.

  3. 03

    Policies that let too much through

    “Not all information present in the JWT should be used in RLS policies.” Supabase, Row Level Security

    RLS can be on and still open: a policy with using (true) for the anon role lets any visitor read every row, and a policy that trusts user_metadata can let users give themselves access, because signed-in users can edit their own metadata. The free RLS policy checker reads a migration and flags both. Then run the free AI app check on the whole app.

  4. 04

    A secret key next to it

    “Never put one in a browser, a shipped application, or source control.” Supabase, Understanding API keys

    If the same code also holds a secret or service_role key, that one skips row-level security entirely. Move those calls to the server and replace the key.

Checked against the vendor’s docs on : Supabase docs: Understanding API keys; Supabase docs: Row Level Security.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Free Supabase RLS policy checker · Free AI app check · Supabase service_role key exposed · Supabase RLS fixes

Questions

More on this error

Should I hide the anon key in an environment variable?

You can keep it in one for convenience, but it still ends up in the JavaScript your site loads, so it stays public. Hiding it isn’t the protection; row-level security is.

Do I need to rotate the anon key?

Not because it’s public: it’s meant to be. Replace the secret or service_role key if that one leaked.

Is the anon key different from the publishable key?

Supabase’s docs call the anon key the legacy version of publishable keys. The advice is the same for both: public by design, and safe only with row-level security on.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; we reply by email, usually within one business day.