v0 security guide
How to secure a v0 + Supabase app
Check every table v0 creates for RLS, keep the Supabase secret key out of any NEXT_PUBLIC_ variable, and make each Server Action or Route Handler that uses the secret key check the user first. v0 adds Supabase through the Vercel Marketplace and can run SQL for you, so review that SQL the way you would review a migration.
Last updated
How do I add Supabase to a v0 project?
- Open Project menu > Settings > Integrations and pick Supabase, or ask for it in the chat.
- Let the integration provision the Supabase account. v0 adds the environment variables to the project.
- From then on, v0 can generate and execute SQL against the database, including statements that drop tables.
Which Supabase variables are safe in v0?
Only variables with the NEXT_PUBLIC_ prefix reach the browser. The Supabase URL and publishable key may carry it. The secret key must not. Search the client build for a secret key before each deploy.
# Look for a secret key before you deploy. This must print nothing.
grep -rnE "sb_secret_|service_role" .next/static/ 2>/dev/nullHow do I check the tables v0 created?
Tables made with SQL do not get RLS on their own. Run the query below in the Supabase SQL editor after v0 changes the schema, then add policies to each table it returns.
-- Tables in public without RLS. This must return no rows.
select c.relname
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relkind = 'r' and not c.relrowsecurity;alter table public.tasks enable row level security;
create policy "tasks: owner reads" on public.tasks
for select to authenticated
using ((select auth.uid()) = user_id);
create policy "tasks: owner inserts" on public.tasks
for insert to authenticated
with check ((select auth.uid()) = user_id);
create policy "tasks: owner updates" on public.tasks
for update to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);How do I guard Server Actions that use the secret key?
The secret key maps to service_role, which skips every policy. A Server Action or Route Handler that holds it is your only check, so write the check first.
- Read the signed-in user from the session on the server, not from a form field or a URL parameter.
- Confirm that user may touch the rows in the request before you run the query.
- Prefer the user's own session with the publishable key, so RLS still applies. Use the secret key only for work no user may do.
- Keep the secret key in a server-only variable without the NEXT_PUBLIC_ prefix.
Should v0 use Supabase MCP tools?
Marketplace integrations can expose remote MCP tools to v0, and the default is Ask for Approval. Keep that default. Supabase's MCP guide names prompt injection as the main LLM-specific attack.
- Scope the connection to one project.
- Use read-only mode for anything that runs unattended.
- Connect to the production project only when a task needs it.
Frequently asked questions
- Can v0 drop my Supabase tables?
- Yes. v0's docs say that for SQL integrations it can generate and execute SQL to create, update and drop tables. Point the integration at a development project while you build, and connect production only when you ship.
- Where should the Supabase secret key live in a v0 app?
- In a server-only environment variable without the NEXT_PUBLIC_ prefix, used only by Route Handlers or Server Actions that check the user first.
- Does v0 scan my database for security issues?
- v0's docs describe no database security scan. They describe a check of NEXT_PUBLIC_ usage. Run the Supabase Security Advisor, or Supahound's free posture scan, for the database side.