The Supabase publishable key, formerly the anon key, is safe to expose in your client, but only because Row Level Security is meant to be doing the real protection. The key itself grants nothing beyond the anonymous role's permissions, and those permissions are governed by your RLS policies, so with RLS enabled and correct policies, exposing it is by design. The danger is not the key; it is an exposed key with RLS disabled, which lets anyone read, modify, or delete your data. The secret key, the service_role or sb_secret key, is different and must never be exposed, because it bypasses RLS entirely.
Short answer
Yes, the publishable or anon key is safe to expose, provided Row Level Security is enabled and your policies are correct. Per Supabase's API keys documentation, the publishable key is designed to be used in browsers and client apps, and it only ever acts with the anonymous role's permissions, which your RLS policies define. Per Supabase's Row Level Security guidance, those policies are what actually restrict access. So the key is safe by design, but only as safe as your RLS. If RLS is off, an exposed key lets anyone read and delete data. Never expose the secret (service_role) key, which bypasses RLS.
What the anon or publishable key is
The anon key, now issued in the newer format as a publishable key, is the public API key Supabase intends for client-side use. When your frontend or mobile app talks to Supabase, it authenticates with this key, which identifies the request as coming from your project and grants it the permissions of the anonymous role, or the authenticated role once a user logs in. It is not a secret; it is a project-scoped identifier for public access.
Crucially, the key does not itself decide what a request can do. It grants a role, and what that role is allowed to read or write is determined entirely by your Row Level Security policies. This separation is the whole point: the key can be public because it is powerless on its own, and the actual access control lives in your database policies rather than in the key.
Is it safe to expose?
With RLS enabled and correct, yes, it is safe to expose the publishable key, and Supabase expects it to be in your client code. Because the key only acts with the anonymous or authenticated role, and RLS constrains those roles to exactly what your policies permit, publishing the key does not by itself give anyone access to anything you have not allowed. This is a deliberate design, not a workaround.
The safety is entirely conditional on RLS, though. The key is safe because something else, your RLS policies, is doing the protecting, so the real question is never is this key safe to expose but is my RLS correct. If you treat the key as safe without confirming RLS, you have not actually secured anything; you have just assumed a control that may not be in place.
The RLS dependency: this is everything
Row Level Security is the control that makes an exposed publishable key acceptable, so it is the thing to get right. RLS lets you write policies at the row level that decide which rows each role can select, insert, update, or delete, for example allowing users to read only their own records. With RLS enabled and least-privilege policies in place, the anonymous role reaches only what you intend.
Enable RLS on every table that the client can reach, and write policies deliberately rather than leaving tables open. A common and serious mistake is enabling RLS but writing an overly permissive policy, which is nearly as bad as no RLS at all. Test your policies as the anonymous role to confirm they actually restrict access, because a policy you have not verified is a policy you cannot rely on.
Can users delete your database?
With proper RLS, no. A user holding your publishable key can only do what your policies allow for their role, so if your policies do not grant delete on a table, they cannot delete its rows, and they cannot touch tables they have no policy for. Correct RLS is exactly what prevents an exposed key from becoming destructive.
Without RLS, yes, and this is the real risk. If RLS is disabled on a table, the anonymous role reaches it with full access, so anyone with your publishable key, which is public, can read, modify, and delete that table's data. The key was never the vulnerability; the missing RLS is. This is why an exposed key on a project without RLS is a genuine emergency, while the same key on a properly secured project is a non-issue.
Publishable versus secret key
Supabase has two very different kinds of key, and the distinction matters enormously. The publishable or anon key is public, respects RLS, and belongs in the client. The secret key, the service_role key in the older format or the sb_secret key in the newer one, bypasses RLS entirely and has full access to your data, which is why it must live only on your server and never appear in client code, a repository, or a mobile app bundle.
Confusing the two is a common and dangerous error. Exposing the publishable key is fine; exposing the secret key is a full compromise, because it ignores every policy you wrote. If you are migrating to the newer key format, keep the roles straight: sb_publishable for the client, sb_secret strictly server-side, and treat any leak of the secret key as an incident requiring immediate rotation.
Keys and RLS compared
The safety of an exposed key depends on the key type and the RLS state. The table below makes the combinations clear.
| Scenario | Safe? | Result |
|---|---|---|
| Publishable key, RLS enabled with good policies | Yes | Access limited to what policies allow |
| Publishable key, RLS disabled | No | Anyone with the key can read and delete data |
| Publishable key, RLS on but permissive policy | No | Access is broader than intended |
| Secret (service_role) key exposed anywhere client-side | Never | Full bypass of RLS, total compromise |
Read the table by your own setup. A publishable key with solid RLS is the safe, intended case, while every other row is a problem, and an exposed secret key is the worst of them regardless of RLS.
Safety checklist
A short check confirms your exposed key is actually safe. The checklist below covers it.
| Check | Action | Done? |
|---|---|---|
| RLS enabled | Turn on Row Level Security for every client-reachable table | [ ] |
| Policies correct | Write and test least-privilege policies per role | [ ] |
| Secret key server-only | Keep the service_role or sb_secret key out of all client code | [ ] |
| Test as anonymous | Verify the anon role cannot read or delete forbidden data | [ ] |
| Migrate keys | Move to the sb_publishable and sb_secret format | [ ] |
The two that matter most are enabling RLS with tested policies and keeping the secret key strictly server-side, because those are what make an exposed publishable key safe and what prevent a catastrophic leak. Testing as the anonymous role is how you turn an assumption that RLS works into a verified fact.
Verify with a scan
The publishable key being public is fine, but two things are worth verifying in an app you ship: that your secret key did not accidentally end up in the build, and that no other sensitive credential is exposed. An assistant or a copy-paste can put a secret key where it does not belong, and that is the dangerous case, not the publishable key.
A scanner like PTKD.com analyzes your app build and reports findings ordered by severity and mapped to OWASP MASVS, including secrets embedded in the binary, so you can confirm that no secret key or other credential shipped in your app. To be clear about the boundary: PTKD does not configure your RLS policies or your Supabase project. It checks the build for exposed secrets, which complements the RLS work that keeps your publishable key safe.
What to take away
- The Supabase publishable or anon key is safe to expose and is meant for client use, but only because Row Level Security does the actual protecting.
- The key only grants the anonymous or authenticated role, and RLS policies decide what that role can read or write.
- Users cannot delete your database with proper RLS; without RLS, an exposed key lets anyone read and delete data, which is the real risk.
- Never expose the secret service_role or sb_secret key, since it bypasses RLS entirely and its leak is a full compromise.
- Enable and test RLS, keep the secret key server-side, and verify with PTKD.com that no secret shipped in your app.




