Is v0 safe? The generated code is the whole question
v0 hands you real Next.js source that you deploy yourself, so there is no hosted platform sitting between your code and your users. That is better for control and it means nothing reviews the app before it ships. Server Components and environment variable prefixes are where the specific mistakes cluster.
v0 sits in a different position from Lovable or Bolt, and that changes the answer to this question. It is worth understanding the difference before you go looking for flaws, because it moves where they are.
Lovable and Bolt are builders and hosts. They generate your app, they run it, and they keep some responsibility for the platform underneath it. v0 generates React and Next.js source code that you take away, put in your own repository, and deploy wherever you like. There is no hosted platform sitting between your code and your users, because the code is simply yours.
That is a genuine advantage. You can read every line, you can put it through code review, you can run whatever tooling you want against it. It also means that when something is wrong, nothing between you and the internet is going to catch it.
What does v0 get right?
The framework defaults are good, and you inherit them for free. That is worth more than it sounds, because defaults are what you get when nobody is paying attention.
React escapes values by default when it renders them, so the cross-site scripting that plagued older template systems is not a default outcome in a v0 app. You have to go out of your way to reintroduce it, usually via dangerouslySetInnerHTML, and the name of that API is doing its job.
Next.js gives you a clean server boundary. Route handlers under app/api/ run on the server, Server Components run on the server, and there is a real place for code that must not reach the browser. Several classes of mistake that are easy in a single-page app are structurally harder here.
The generated components themselves are usually sound. v0 is very good at the thing it is aimed at, which is producing well-formed, accessible, idiomatic UI code.
Where do v0 apps actually break?
In the seams between that UI and everything behind it, and in one Next.js specific trap that catches people repeatedly. None of these are v0 doing something wrong so much as v0 not being asked.
The NEXT_PUBLIC_ prefix is an instruction, not a label. Any environment variable with that prefix is compiled into the JavaScript bundle and shipped to every visitor. It is meant for values that are safe in public, like a Supabase publishable key. What happens in practice is that a variable does not work in a client component, the error says it is undefined, adding the prefix makes the error go away, and a service role key is now in your bundle. Run grep -rn "NEXT_PUBLIC_" .env* and read every value: if you would not print it on your homepage, it is in the wrong variable.
The Server Component boundary is easy to cross by accident. Server Components can read secrets and query the database directly, and that is the point of them. Add "use client" at the top of a file to make a button interactive, and everything in that file now runs in the browser, including whatever it was reading. The mistake looks like a small refactor and it moves a whole file across a security boundary.
Route handlers have no authentication unless you write it. v0 will happily generate app/api/orders/route.ts that queries your database and returns rows. Whether it checks a session first depends entirely on whether you asked. A protected page in front of an unprotected route is not protection: curl the route with no cookie and see what comes back.
Middleware protects paths, not data. middleware.ts is the usual answer for gating routes in Next.js, and it is a good one for pages. It does not know that order 1041 belongs to a different user than the one asking. Path-level auth and record-level ownership are separate problems and only one of them is solved by a matcher config.
Is it more or less risky than a hosted builder?
Different rather than simply more or less, and the honest answer depends on you. The trade is a real one in both directions.
You lose the safety nets. Bolt runs an optional automated review before publish and Lovable runs a configuration scan on publish, and neither of those is deep, but both are more than zero. With v0 there is no publish step that anybody inspects, because you deploy your own code on your own schedule.
You gain everything else. Your code is in a repository you control, which means you can run static analysis, add pre-commit hooks, review diffs, and use any security tooling that reads a Next.js codebase. None of that is available to you when the app lives inside somebody else's builder.
The practical answer is that v0 is safer for someone who will use that control and riskier for someone who will not. If the code went straight from v0 to Vercel without being read, you have all the exposure of a hosted builder and none of the review.
What should I check first?
Four things, in this order, and the first two take about five minutes between them. Stop at the first one that fails rather than working through the whole list.
1. Grep your environment files. grep -rn "NEXT_PUBLIC_\|VITE_" .env* and read each value. Anything a stranger should not have is in the wrong place. The full version of this check is here.
2. Curl a sensitive route with no session. curl -i https://yourapp.com/api/<something-that-returns-data> and look at the status. A 200 with a body is your answer, and you should be seeing a 401 or 403.
3. Try to read another user's record. Make a second account, take a URL or an API path with an id in it from the first, and request it as the second. This is the flaw that shows up most in generated apps of every kind.
4. Check your database rules. If you wired v0 to Supabase, RLS is off by default on new tables, and enabling it does not revoke the grants that were handed out when the table was created. The four steps that actually close it covers the part most guides skip.
Where this leaves you
v0 is a good tool that produces good UI code and hands you the result honestly. The security question it raises is not about v0 at all, because the thing that will be exposed is your route handlers, your environment variables and your database rules, none of which v0 claimed to be responsible for.
Since the code is yours and sitting in a repository, you are also in the best position of any of these platforms to have something read it properly. That is what Sentrint does: your whole repository, in plain English, with a fix you can paste back into v0 or into Cursor. A code scan, not a pentest, and the first one is free with no card.
Run the grep today regardless. It is one command and it finds the mistake that costs the most.