← Stack guides

v0

Security for your v0 app

v0 generates beautiful React and Next.js interfaces, but it focuses on the frontend: the backend security is on you. That is where exposed keys, unprotected fetches and "hidden" buttons that protect nothing slip in. Scan your app and confirm it.

Typical risks in v0

Client-side fetch with the key in plain sight

The code v0 generates often calls APIs directly from the component. If that call carries a key, it travels to the browser and anyone reads it in DevTools.

Actions that never check the session

v0 hides a button when you should not see it, but it does not validate the session on the server. The action is still a public URL anyone can call directly.

No headers or CSP by default

Being UI-first code, what comes out of v0 ships without security headers or a Content-Security-Policy. You must configure them wherever you deploy.

"v0 security" is two things worth keeping apart. The first is the v0 project: who can see your chats, where environment variables live, what integrations add and where it gets deployed. The second is the code v0 generates: very polished Next.js interfaces that, by design, focus on what is visible and leave for later what is not, which is exactly authentication, validation and headers. This guide covers both, with a block of project instructions, a review prompt before deploying and the checks from outside. The model of what runs on the server and what reaches the browser is in the Next.js guide.

Part 1: securing your v0 project

Public and private chats

A v0 chat can be shared by link or published to the community, and in both cases it shows the full code and the prompt history, including any key you pasted into the conversation and the names of your environment variables. Check each chat's visibility before sharing it, and assume that everything you wrote in a public chat has already been read by someone.

Environment variables and integrations

v0 has a per-project environment variables panel that is used in the preview and synced to Vercel on deploy. That is the only place for keys: never the chat, never a file in the code. Integrations (Supabase, Neon, Upstash, Blob and the rest of the Vercel marketplace) add their variables there automatically; the ones starting with NEXT_PUBLIC_ reach the browser and the rest only the server. If a secret key has that prefix, it is exposed even though you put it in the panel.

Preview and deployment

The preview inside v0 runs your app with your real variables. Deployment goes to Vercel, with everything that implies: previews public by default, variables per environment, firewall and deployment protection. The Vercel guide goes through it; the first thing to enable is Deployment Protection.

If you connect a database

With Supabase, Neon or any Postgres, the tables v0 creates are born without access policies and with the schema the model imagined. If it is Supabase, the Supabase guide has three SQL queries to audit it in a minute; with other databases, access is controlled by your server code and the rules in part 2 apply.

Part 2: the flaws v0 puts into your code

  • No authentication. v0 builds the dashboard, the table and the buttons; the login arrives "in the next prompt" or never. A deployed app with a dashboard and no session is entirely public.
  • Sample data that stays. Fake users, test keys and an admin / admin in a data file that ends up in production.
  • fetch from the component with the key inside. The call to the external API goes in the client component, with the key in plain sight in the browser tools.
  • Server Actions and Route Handlers that do not check the session. The button is hidden if you are not an admin, but the action is still an endpoint anyone can invoke.
  • Pretty forms without server validation. The field has rules on the client; the action accepts whatever arrives.
  • dangerouslySetInnerHTML for rich content. Perfect for the demo, XSS in production if a user writes the content.
  • Remote images with a wildcard. remotePatterns with hostname: '**' so that "any image works".
  • No headers, no CSP. The next.config comes out of generation empty.

A block of instructions for the project

Paste it into the project instructions in v0 or, if you do not use them, at the start of your first prompt, so it holds for every generation:

Security rules for this project:
- Every dashboard page and every action that reads or writes data checks the session on the server. If there is no authentication system, build it before any dashboard.
- Calls to services with a key go in Route Handlers or Server Actions, never in client components. No secret key carries the NEXT_PUBLIC_ prefix.
- Every Server Action and every Route Handler validates its input with a schema before touching data.
- Pass client components only the fields they need, never the whole user object.
- No sample data with credentials; if test data is needed, mark it and tell me so I remove it before deploying.
- Do not use dangerouslySetInnerHTML with user content.
- images.remotePatterns lists specific domains. next.config defines security headers and does not enable productionBrowserSourceMaps.

A review prompt before you deploy

Review the security of this project and do not change anything yet. Answer with a list:
1. Pages, Server Actions and Route Handlers that read or write data without checking the session.
2. Client components that call external services with a key, and NEXT_PUBLIC_ variables containing secret keys.
3. Sample data, credentials or test keys in the code.
4. Actions without input validation and uses of dangerouslySetInnerHTML.
5. remotePatterns with a wildcard, missing security headers and productionBrowserSourceMaps enabled.
For each point, propose the exact change and wait for my confirmation.

Check the result from the outside

curl -sI https://yourdomain.com | grep -iE "strict-transport|content-security|x-frame|x-content-type"
curl -s -o /dev/null -w "%{http_code}\n" https://yourdomain.com/dashboard
curl -s https://yourdomain.com | grep -oE '/_next/static/chunks/[^"]+\.js' | head -3

Expected: headers present and a redirect (302 or 307) to the login on the second line; a 200 means the dashboard is public. Open the chunks from the third command and search for sk_, Bearer and the names of your services. Scanaris runs these checks and about forty more in 30 seconds: it detects that the app is Next.js deployed on Vercel, looks for secrets in the chunks, checks source maps, headers, CSP, cookies, CORS and exposed files, reviews your metadata and gives you a fix prompt for each failure to paste into v0. And it can rescan every day, because a regeneration can bring back a fixed flaw.

Frequently asked questions

Is v0 code production-ready?

The interface is; security is not included. Before deploying anything with real data it needs authentication, server validation and headers, which is what the block and the prompt above go through.

Does deploying from v0 make my app private?

No. The deployment is public like any other on Vercel, and so are the previews. Privacy comes from your session system and Deployment Protection.

What do I do if I pasted a key into the chat?

Rotate it at the source service even if you delete it: the chat keeps it and, if it was public, anyone has already seen it. Then add it in the environment variables panel and ask v0 to move the call to the server.

Related checks

Does your v0 app pass these checks?

Scan it free and get a fix prompt for every issue we find.

Scan my site free