AI-coded apps

    Is Supabase Publishable Key Safe to Expose?

    A Supabase project showing the publishable key used client-side while Row Level Security policies govern what the anonymous role can access.

    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.

    ScenarioSafe?Result
    Publishable key, RLS enabled with good policiesYesAccess limited to what policies allow
    Publishable key, RLS disabledNoAnyone with the key can read and delete data
    Publishable key, RLS on but permissive policyNoAccess is broader than intended
    Secret (service_role) key exposed anywhere client-sideNeverFull 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.

    CheckActionDone?
    RLS enabledTurn on Row Level Security for every client-reachable table[ ]
    Policies correctWrite and test least-privilege policies per role[ ]
    Secret key server-onlyKeep the service_role or sb_secret key out of all client code[ ]
    Test as anonymousVerify the anon role cannot read or delete forbidden data[ ]
    Migrate keysMove 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.
    • #supabase
    • #publishable key
    • #anon key
    • #row level security
    • #rls

    Frequently asked questions

    What is the Supabase anon or publishable key?
    It is the public API key Supabase intends for client-side use. Your frontend or app authenticates with it, which identifies the request as coming from your project and grants it the anonymous role, or the authenticated role after login. It is not a secret and does not itself decide what a request can do; the permissions of that role are defined entirely by your RLS policies.
    Is it safe to expose the Supabase publishable key?
    Yes, with Row Level Security enabled and correct policies, and Supabase expects the key in client code. It only acts with the anonymous or authenticated role, and RLS constrains those roles to what your policies permit, so publishing it grants nothing you have not allowed. The safety is conditional on RLS, so the real question is whether your RLS is correct.
    Can users delete my database with the publishable key?
    Not with proper RLS. A user holding the key can only do what your policies allow for their role, so if no policy grants delete on a table, they cannot delete its rows, and they cannot touch tables with no policy. Without RLS, yes: the anonymous role reaches the table fully, so anyone with the public key could read and delete that data.
    Does the publishable key require RLS?
    In effect, yes, for the key to be safe. RLS is the control that makes an exposed publishable key acceptable, so enable it on every client-reachable table and write least-privilege policies. Enabling RLS but writing an overly permissive policy is nearly as bad as no RLS, so test your policies as the anonymous role to confirm they actually restrict access.
    What is the difference between the publishable and secret key?
    The publishable or anon key is public, respects RLS, and belongs in the client. The secret key, the service_role key or the newer sb_secret key, bypasses RLS entirely and has full data access, so it must live only on your server and never appear in client code, a repository, or an app bundle. Exposing the secret key is a full compromise.
    How do I check that no secret key shipped in my app?
    Verify the build, since an assistant or a copy-paste can put a secret key where it does not belong, which is the dangerous case, not the publishable key. A scanner like PTKD.com (https://ptkd.com) analyzes your build and reports secrets embedded in the binary, mapped to OWASP MASVS. It does not configure your RLS, but it confirms no secret credential shipped in your app.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free