One of seven checks in the Full Scan

Check whether your app ships secret keys to the browser

Everything in your app's JavaScript is public. Anyone can open the page source and read it. If a secret key ends up in the bundle, every visitor has it. This check reads your live app the way a visitor's browser does and looks for keys that should never be there.

Which keys are fine in the browser and which are not

Some keys are designed to be public. A Supabase anon key or publishable key is meant to sit in the browser; your row-level security policies decide what it can read. A Supabase service role key or secret key is the opposite: it skips every policy and can read and change any row.

The check knows the difference. It flags secret keys as critical and leaves the public key alone, because what the public key can reach is decided by your database rules, which the database checks cover.

How the check works

LeakScan downloads the JavaScript files your home page loads, the same files a browser downloads, and matches them against known key patterns. It sends nothing a normal visitor would not send.

How it gets fixed

Secret keys belong on a server, in an edge function or in an environment variable that is never exposed to the client. The fix prompt tells your builder to move the code that uses the key into a server or edge function, and to rotate the key, because it has already been public.

Common questions

Is the Supabase anon key safe to have in my frontend?

Yes, as long as row-level security is on for every table and your policies are tight. Without row-level security, the anon key can read whole tables.

How do secret keys end up in the bundle?

Usually through an environment variable with a public prefix, such as VITE_ or NEXT_PUBLIC_, or a key pasted straight into a component while the builder was fixing an error.