← All fixes

Fix it

v0 exposed my Supabase key, how to fix it

High severityCWE-798 (Use of Hard-coded Credentials)
We scanned nearly 2,000 AI-built apps and 1 in 8 shipped a high-severity flaw. Is this one in yours?Scan free →

If v0 wrote a Supabase key into your code, the fix depends on which key it is. The anon key is meant to be public but is only safe with Row Level Security configured. The service_role key must never reach the browser and needs immediate rotation if it did. Start by identifying which key you have.

Why it's a problem

An exposed anon key with no RLS lets anyone read and write your whole database. An exposed service_role key is worse: it bypasses RLS entirely and grants full admin access. In a Next.js app, the risk is compounded because a key used in a client component or behind a NEXT_PUBLIC prefix ships to every visitor's browser.

How to fix it, in order

  1. 1Identify the key. If it starts as a JWT used for the public client, it is the anon key. If it is labeled service_role or used to bypass rules, treat it as the secret key and rotate immediately.
  2. 2For the service_role key, rotate now. Regenerate it in Supabase and remove it from all client code; it must live only in server code.
  3. 3For the anon key, turn on RLS. Enable Row Level Security on every table with policies that scope access to the row owner. The public key is only safe behind RLS.
  4. 4Keep secret keys server-side. Use any secret key only in server components or route handlers, read from an environment variable, never with a NEXT_PUBLIC prefix.

Why v0 does this

v0 generates client components by default, and when data access needs a key the quickest working version puts it in that client code. It does not distinguish the public anon key from the secret service_role key, or reason about whether the code runs on the server.

Stop it happening again

In Next.js, the anon key can live in the client if RLS is on; the service_role key never can. Keep secret keys in server code, enable RLS on every table, and scan the app to confirm no secret key reaches the browser.

The quick fix

  • Identify whether it is the anon key (public, needs RLS) or service_role key (rotate now).
  • Enable Row Level Security on every table.
  • Keep secret keys server-side, never behind NEXT_PUBLIC.
  • Rotate any service_role key that reached client code.

Common questions

How do I tell which Supabase key v0 used?

Inspect the generated code. The anon key is the shorter JWT used in the public createClient call. A service_role key is longer and grants admin access; it must be rotated immediately if found in client code.

If v0 used the anon key in a client component, is that acceptable?

With RLS properly configured on every table, yes. Without RLS, the anon key gives anyone who reads your bundle full access to your database.

How do I enable RLS in a Next.js app that uses Supabase?

In the Supabase dashboard, enable RLS on each table, write policies that restrict access to the authenticated user's rows, and test by attempting to read data as a non-owner.

Want to know if this pattern is already in something you shipped? Scan your live app or a public repo free, no account needed.

Scan my app →

Related: v0 security overview

Catch this automatically: scan your GitHub repo · secret scanner · review every pull request · SAST for AI code · OWASP Top 10 for AI code

v0 Exposed My Supabase Key, How to Fix It | Prbl