Justin McKelvey
Ran snowboard shops. Taught myself to code. Now I build AI that does real work.
Supabase Anon Key vs Service Role Key (Now Publishable vs Secret): Which One Is Safe in Your Frontend?
TL;DR: As of November 2026, Supabase has four key names for two jobs. The anon key, now called the publishable key, is built to sit in your frontend, and it's safe there only when Row Level Security (RLS) is on for every table. The service role key, now called the secret key, bypasses every RLS rule you have and must never touch a browser. Supabase plans to delete the legacy anon and service_role keys in late 2026, so if your app still uses them, the clock is running.
I've been a CTO at an AI startup and shipped 50+ products, and when I open a Supabase app built with Lovable, Bolt or Cursor, this is the first thing I check. Which key is in the browser bundle? It takes about two minutes to answer, and the wrong answer is the whole database.
The four Supabase keys side by side
| Key | Status | Looks like | Postgres role | Obeys RLS? | Where it goes |
|---|---|---|---|---|---|
| Publishable key | Current | sb_publishable_... |
anon, or authenticated once a user signs in | Yes | Browser, mobile app, anything you ship |
| anon key | Legacy version of publishable | Long JWT starting eyJ
|
anon, or authenticated | Yes | Same as publishable, until you migrate |
| Secret key | Current | sb_secret_... |
service_role | No, bypasses it | Your server, Edge Functions, cron jobs only |
| service_role key | Legacy version of secret | Long JWT starting eyJ
|
service_role | No, bypasses it | Server only, until you migrate |
Supabase's own docs put it in one picture I like: your data is a building, the publishable key is taped to the front door and only opens the lobby, and the secret key is the master key that stays in your pocket. RLS is the set of locks on every room past the lobby.
How the keys actually decide what someone can see
A key doesn't hold permissions by itself. Every request to your Supabase project carries a key, and Supabase turns that key into a Postgres role. The role is what your database checks.
The publishable key (and the legacy anon key) becomes the anon role. If the visitor has signed in through Supabase Auth, the same key plus their login token becomes the authenticated role. Your RLS policies are written for those two roles, so they decide row by row what each request gets back. A signed-in customer sees their own orders. A stranger sees nothing.
The secret key (and the legacy service_role key) becomes the service_role role. That role carries a Postgres attribute called BYPASSRLS, which means policies are never checked for it. Supabase says plainly that secret keys provide "full access to your project's data, bypassing Row Level Security." That's on purpose: your server needs to run admin jobs like sending receipts or cleaning up old records.
So the key in your frontend sets the ceiling on what any stranger on the internet can do. Publishable key with RLS on: the policies decide. Secret key in the frontend: no ceiling at all.
Is the anon key safe in your frontend?
Yes, with one condition. Supabase's docs say "your publishable key is safe to expose with RLS enabled." Anyone can open the browser's network tab and read it, and that's expected. It works like a project ID.
The condition is the part vibe-coded apps miss. When RLS is on and a table has no policies, Supabase returns no rows to the publishable key at all. When RLS is off, that same public key can read, edit and delete every row in the table. Supabase's Security Advisor flags that case as an ERROR called "Table publicly accessible."
That's how Moltbook went wrong in early 2026. Wiz found a Supabase key in the site's client code and no RLS policies behind it, which exposed 1.5 million API tokens, 35,000 email addresses and private messages. A public key with RLS on would have returned nothing. Whether the platform as a whole is safe to build on is a separate question, and I answer it in is Supabase secure.
Why the service role key can never go in the browser
Because it skips every lock. If your secret key or service_role key ends up in frontend code, anyone who opens your site can copy it and get full read and write access to your whole database, RLS or not.
The usual way it gets there in an AI-built app: the builder needs to do something the logged-in user isn't allowed to do, the agent hits a permission error, and the "fix" is to swap in the key that has no permissions to hit. The error goes away. So does your security. Watch for any environment variable with VITE_ or NEXT_PUBLIC_ in front of a secret key, since those prefixes exist to ship values to the browser.
The new secret keys add one guard: Supabase rejects them with a 401 when the request comes from a browser. Don't lean on that. Supabase's own docs point out that an attacker can still use a leaked key from any other tool. The guard stops your app from working with the wrong key. It doesn't stop someone who copied it.
If your app was built in Lovable, what the platform checks for you and what it leaves to you is in is Lovable secure.
Where to find each key in the dashboard
- Publishable key and project URL: open your project and click Connect. It shows both, formatted for your framework.
- Every key, new and legacy: Settings, then API Keys. Supabase says there is no separate Settings, then API page anymore, which is why older tutorials send people to a menu that isn't there.
- No publishable or secret key listed yet? Create them on that same API Keys page. Creating them doesn't revoke your legacy keys. Both sets work side by side until you disable the old ones.
A quick way to tell what a tutorial assumes: new keys are short strings with an sb_ prefix. A long key starting with eyJ is a legacy JWT.
The deadline: legacy anon and service_role keys
Supabase's official timetable runs like this. New publishable and secret keys arrived in June 2025 and fully launched in July 2025. Since November 2025, new projects no longer get the legacy anon and service_role keys, and projects restored from November 1, 2025 come back without them. The last row reads "Late 2026, TBC: Legacy API keys will be deleted," with the note that you have to migrate by then "or your app will break."
We're in late 2026 now. If your app was generated a year or more ago, there's a good chance both keys in it are legacy JWTs. Moving is mostly a find-and-replace: publishable where you had anon, secret where you had service_role, then disable the legacy pair in Settings, then API Keys once everything works. Supabase's comparison with Firebase on the rest of the stack is in Supabase vs Firebase.
Leaked the wrong key? What to do today
- Assume it's been copied. If a secret or service_role key was ever in frontend code or a public repo, treat it as public.
- Make a new secret key in Settings, then API Keys, and move your server code to it.
- Disable the leaked key. For a legacy service_role key, follow Supabase's guide to rotating a leaked or compromised key.
- Turn RLS on for every table and add policies, so the publishable key in your frontend only reaches what each user should see.
- Check what was read. If the key sat in the open for weeks, look at your logs and decide whether users need to hear from you.
Your five-minute check
Open your live app in Chrome, right-click, Inspect, and go to the Network tab. Reload, click any request to supabase.co, and look at the apikey header. If it starts with sb_publishable_, good. If it's a long eyJ string, paste it into a JWT decoder and read the role field: anon is fine, service_role means stop and rotate today. Then open the Security Advisor in your Supabase dashboard and clear every "Table publicly accessible" error.
The key check is item three on my free vibe coding security checklist, which has 19 more like it. If the advisor comes back red and you'd rather have someone go through the whole app, that's what Vibe Code Rescue starts with: a free repo audit.
Sources
- Supabase Docs, API keys: four key types, role mapping, BYPASSRLS, browser 401, where keys live. Read November 3, 2026.
- Supabase, Upcoming changes to Supabase API keys: the timetable, including "Late 2026, TBC" deletion of legacy keys. Read November 3, 2026.
- Supabase Docs, Securing your data: publishable key safe with RLS enabled; secret and service role keys never safe to expose. Read November 3, 2026.
- Supabase Docs, Row Level Security: no data reaches a publishable key until policies exist. Read November 3, 2026.
- Supabase Docs, Rotate a leaked or compromised API key. Read November 3, 2026.
- Wiz, Exposed Moltbook database (February 2, 2026): 1.5 million API tokens and 35,000 emails behind a client-side key with no RLS. Read November 3, 2026.
Ship AI-built code without the 2am surprise
The free 20-point security checklist I run on every AI-built codebase before it touches real users.
Frequently Asked Questions
- Is it safe to expose the Supabase anon key?
- Yes, if Row Level Security is on for every table. The anon key (now called the publishable key) is designed to ship in browser code, and Supabase's docs say it is safe to expose with RLS enabled. It only reaches what your RLS policies allow. If a table has RLS off, anyone holding that key can read and change the table.
- What is the difference between the anon key and the service role key?
- The anon key maps to the anon Postgres role (or authenticated, once a user signs in), so your Row Level Security policies apply to it. The service role key maps to the service_role role, which has the BYPASSRLS attribute, so it skips every policy and can read and write all your data. Anon goes in the frontend. Service role stays on a server.
- What are the new names for the Supabase anon and service_role keys?
- The anon key's replacement is the publishable key (starts with sb_publishable_). The service_role key's replacement is the secret key (starts with sb_secret_). The new keys are short strings, not JWTs. If a tutorial tells you to copy a long key that starts with eyJ, it was written for the legacy keys.
- Where do I find my Supabase anon key or service role key?
- In the Supabase dashboard, open your project, then Settings, then API Keys. Every key lives there, legacy or new, and Supabase says there is no separate Settings > API page anymore. The Connect button at the top of the project also shows your project URL and publishable key ready to paste into a .env file.
- When will the legacy anon and service_role keys stop working?
- Supabase's official timetable says legacy API keys will be deleted in late 2026, date to be confirmed, and that apps still using them will break. Projects created or restored since November 2025 no longer get the legacy keys at all. As of November 2026, the safe move is to switch to publishable and secret keys now.
- What should I do if my service role key leaked?
- Rotate it today. Create a new secret key in Settings, then API Keys, move your server code to it, then disable the leaked key (for a legacy service_role key, follow Supabase's rotate-a-leaked-key guide). Supabase blocks secret keys in browsers with a 401, but an attacker can still use a leaked key from any other tool, so the block is not a fix.
More on Vibe Code Rescue
What Is Prompt Injection? How It Hits the AI Feature You Added to Your Lovable or Cursor App
Prompt injection is when text your AI feature reads carries instructions the model follows instead of yours. OWASP ranks it the #1 risk for AI apps, and there's no full fix. Here's what it looks like in a founder's app, three real cases, and the fixes that limit the damage.
Is Supabase Secure? Yes, If RLS Is On: How to Check Yours in 5 Minutes (2026)
Supabase the platform is secure: SOC 2 Type 2, encrypted data, regular pen tests. Your app on Supabase is only as secure as its Row Level Security rules, and those are yours to set. Here's what Supabase covers, what you own, how RLS works in plain English, and a 5-minute check for a Lovable or Bolt app.
How Much Does It Cost to Audit or Fix a Vibe-Coded App? ($0 to $50K, What Each Tier Finds)
Auditing a vibe-coded app costs $0 to about $1,500. A pen test adds roughly $3,000 to $6,000. Fixing what the audit finds is the real bill: $15K to $50K for most rescues. Published prices for every tier, what each one actually catches, and which one you need.
Best Security Scanners for Vibe-Coded Apps (2026): 12 Tools, Free Ones First
Twelve scanners for apps built on Lovable, Bolt, Replit or Cursor, with what each one actually catches and what it costs today. Six cost $0 for a two-person team, and two more come with tools you already pay for. None of them catches the bug that leaks the most data.
Written by
Justin McKelvey
I spent 12 years running snowboard and mountain-bike shops in Colorado, then taught myself to code. Since then: 50+ products shipped, Head of Product at a national sports platform, CTO at an AI startup. Now I put AI to work in real businesses in Austin, TX and remote, and write down what actually works.
Work with meWant more help? Get the free security checklist · Get a free 20-min repo audit