Skip to main content
Article

I vibe-coded my app: what must I check before launch, and when is a paid pentest worth it?

Vibe coding security before launch: Supabase RLS, keys in the front end, IDOR, public buckets, rate limits and repo secrets, and when a paid pentest pays off.

Ramin MoradiWritten by Published 12 min read
A hand points at a red-flagged warning line in an AI-assistant code editor on a laptop, with a chat panel on the left. A phone on a stand shows a simple sign-in screen, with a mug, a pen pot and an open notebook on the desk.
Contents

Before launch, check six things yourself: Row Level Security is on for every table, no secret key sits in the code your browser downloads, one user cannot open another user's records, file buckets are private, sign-up and paid endpoints have limits, and the repository holds no live credentials. Pay for a manual test once the app holds personal data, takes money or has more than one kind of user.

The failures in vibe-coded apps are rarely exotic. The builder writes a working app, the database behind it will answer requests the app itself never sends, and nobody checks what a stranger can ask for.

Here is the order we would run the checks on a Lovable, Bolt or Cursor app backed by Supabase. The sections below say exactly what to look at for each one.

  1. Row Level Security on every table in an exposed schema, with no policy that lets everyone through
  2. Secret or service_role keys in the front-end bundle
  3. Records reachable by changing an ID
  4. Public storage buckets
  5. Rate limits on sign-up, login and anything that costs you money
  6. Credentials in the Git history

What does vibe coding security mean in practice?

Vibe coding security is mostly access control. An AI builder ships front-end code that talks straight to a hosted database, so the database's own rules are often the only thing between a visitor and your users' data. If those rules are missing or wide open, the app still looks fine in the browser.

The numbers from this month show how often that happens. Crissy Field, a Hamburg application-security firm, looked at 159,041 Lovable projects from December 2025 to September 2026. Of these, 34,545 used Supabase, and 24,664 sent database records as soon as the page loaded. With extra read-only requests the researchers found records containing email addresses on 7,403 of those 24,664 sites (30%).

Crissy Field is careful about that figure. It says the 30% "should therefore not be read as a confirmed data leak rate", partly because some addresses are public contact details or test data. The worst cases were still bad: one service provider exposed "more than 1,000 records containing identity document details, including passport numbers, expiration dates, and nationalities". The firm sells security reviews, so read its conclusion with that in mind. Its advice is that access permissions, interfaces and the separation between user accounts should be reviewed before an app handles real customer data.

None of this was new in 2026. Matt Palmer and a colleague scanned Lovable sites in March 2025 and reported 303 endpoints across 170 projects with inadequate RLS settings, about 10.3% of the 1,645 they analysed. That became CVE-2025-48757.

Is Row Level Security switched on for every Supabase table?

Check it first, because Palmer's 2025 findings came down to missing or weak RLS. Supabase's docs say: "A table in an exposed schema without RLS is readable and writable by any role with a grant on it. Enable RLS on every table in an exposed schema" (Supabase, Row Level Security).

In the SQL editor, run select tablename, rowsecurity from pg_tables where schemaname = 'public'; and look for any false. Repeat it for every schema listed under Exposed schemas in your API settings. The same page warns that views "bypass RLS by default", so a view built over a protected table needs the same attention as the table.

The same docs add one detail people miss. On projects that still grant the anon and authenticated roles access by default, Supabase says to revoke those grants, because "Adding policies doesn't remove them."

Do your RLS policies actually stop strangers?

RLS being on proves nothing if the policy says yes to everyone. Lovable's own scanner looks for exactly this: tables without row-level security and "access rules that let everyone through" (Lovable docs, Security). In SQL, the usual culprit is a policy whose condition is using (true) on a table that holds anything private.

Read every policy against one question: which rows should a signed-out visitor see, and which should a signed-in user see? A profiles table usually needs auth.uid() = id or an owner column, and a waitlist table usually needs no public read at all. Palmer's 2025 follow-up shows why the signed-out case matters. On one Lovable site RLS "appeared active for authenticated requests", but "removing the authorization header bypassed all access controls", and he could write a record with "payment_status": "paid" without going through Stripe (Palmer's statement).

Is a secret key shipped in your front-end bundle?

Open your live site, press F12, and check the Network tab for requests to supabase.co. The key in those requests should be a publishable key (sb_publishable_...) or the legacy anon key. If you see a secret key or the legacy service_role key, treat it as leaked. Supabase says a secret key "bypasses every Row Level Security policy you have. Never put one in a browser, a shipped application, or source control" (Supabase, API keys).

The publishable key is meant to be public. Supabase's table of key types lists it as "Safe to expose online", and says anyone can read it, "so it only reaches what Row Level Security allows". That is why the RLS checks come first: the public key is only as safe as your policies.

Search your built JavaScript for sb_secret_ and service_role as well, since a key can sit in a bundle without being called on the page you opened. Supabase's key guide warns that server-only variables must never carry the public prefix: "Never prefix these, or your bundler will ship the key." It also notes that the newer secret keys refuse browser requests with HTTP 401, a check the legacy service_role key does not have. Supabase plans to deprecate the legacy anon and service_role keys by the end of 2026, so moving to the new keys is worth doing anyway.

Can one signed-in user open another user's records?

Sign up as two test users, create a record as user A, then try to read, edit and delete it as user B by changing the ID in the request. This is the flaw OWASP ranks first in its API list. It says attackers exploit it "by manipulating the ID of an object that is sent within the request", and that every endpoint receiving an object ID "should implement object-level authorization checks" (OWASP API1:2023).

In a Supabase app the fix usually lives in the policy. It can also live in an Edge Function or API route that uses the secret key, because that code skips RLS entirely. Lovable's Deep scan names this case: "server code that bypasses the rules your database enforces". Any function holding the secret key has to do its own ownership check.

Are your storage buckets public?

Check which buckets are marked Public and what is in them. Supabase's bucket docs say a public bucket "effectively bypasses access controls for both retrieving and serving files within the bucket", so "anyone who possesses the asset URL can readily access the file" (Supabase, Storage buckets). Avatars and product photos can live there. ID scans, invoices and contracts cannot.

Private buckets are governed by RLS policies on storage.objects, and Supabase notes that "By default Storage does not allow any uploads to buckets without RLS policies" (Supabase, Storage access control). So the same policy review applies: who can list, read and upload, and in which folder.

Do sign-up, login and paid endpoints have rate limits?

Supabase Auth has rate limits on its own endpoints, and you can tune some of them under Authentication > Rate Limits; past the limit it returns "a 429 Too Many Requests error" (Supabase, Auth rate limits). Your own functions get no such protection unless you add it. The ones to look at are anything that sends email or SMS, calls a paid AI API, or creates records for free.

OWASP lists "Third-party service providers' spending limit" among the limits an API is vulnerable without. Its example is an upload endpoint with no limit and no cost alerts, where "the next monthly bill increases from US$13, on average, to US$8k" (OWASP API4:2023). A spending cap at your AI or email provider is a cheap backstop while you add per-user limits.

Are there live credentials in your Git history?

Look for API keys, database passwords and tokens in the repository, including old commits. Deleting a file does not remove it from history. On GitHub, secret scanning "scans your entire Git history on all branches of your repository" and runs automatically for free on public repositories (GitHub Docs, secret scanning).

If it finds something, rotate the key first. GitHub's own advice is to rotate the affected credential immediately, and it calls rewriting history "time-intensive and often unnecessary if you've already revoked the credential". Lovable also says its front-end code cannot hold secrets safely and steers pasted API keys into its Secrets store instead of the code.

Is the builder's built-in security scan enough?

It is enough to catch the obvious misses, and you should run it before you publish. Lovable's Quick scan runs on every publish and checks database access rules, dependencies and MCP server exposure; its Deep scan reads the whole codebase for access-control, injection, leaked-secret, payment and sign-in issues. Lovable is direct about the limit: the scans "do not replace a thorough security review" and "cannot guarantee complete security".

Scanners also have a history of missing the subtle cases. In May 2025 Palmer wrote that the scanner Lovable had then "merely checks for the existence of any RLS policy, not its correctness". The Deep scan described today goes further than that, but a static read of your code still cannot tell whether a policy matches what your business intends. Lovable's own recommended order is to run the scanners, fix what they find, "then validate with a pentest before a major release".

If your app also hands an AI agent tools or data, the access questions get wider. Our guide to AI agent security covers how much access an agent should get.

When is a paid pentest worth it, and when is a scan or self-check enough?

A self-check and the builder's scan are enough for a prototype with no real users, an internal tool for one person, or a site that stores nothing private. A paid test is worth it once the app holds personal or payment data, has several user roles or tenants, or a customer asks for a report. Buy it before launch, not after a user finds the hole.

Your app

What to do first

Why

Prototype or demo, test data only

The six self-checks plus the builder's scan

Nothing private to lose yet, and the fixes are cheap now

Live app, sign-ups but nothing sensitive

Self-checks, then an automated scan

Catches known issues and missing headers before real users arrive

Users can see or change their own records

A manual test of common exploits

ID swapping and permissive policies need someone trying them

Personal data, payments, ID documents, or a B2B buyer asking for a report

A full manual pentest with exploitation and validation

Each finding needs proof, and a buyer or auditor will ask for it

Our security audit and penetration testing page lists the tiers in that order. Lite, at $250, is a "Vulnerability scan and summary report". Plus, at $500, is "Manual testing of common exploits with detailed recommendations". Pro, at $2,500, is an "In-depth manual penetration test, with exploitation and validation of findings", and the page says it "suits an application that holds customer data and needs each finding exploited and validated". These are starting prices, and the page says "The quote follows the written scope."

For a vibe-coded app with logins, one line on that page matters more than the tier name: "a grey-box test with an account for each role covers more of the app for the same money." Give the tester two accounts per role and the ID-swap check from earlier gets done properly.

If you are still deciding between a scan and a manual test, penetration testing vs vulnerability scanning compares them side by side, including AI pentest tools. For what other providers charge and what drives the price, see penetration testing cost.

FAQ

Is vibe coding secure?

It can be. Crissy Field puts it plainly: "Access control mistakes can happen in any application, whether written by people or built with AI." The risk is that a vibe-coded app often ships with access rules nobody has read. Run the six checks before real users arrive.

Is it safe to have the Supabase anon key in my front end?

Yes, if RLS is on and your policies are right. The anon key and the newer publishable key are designed for the browser and only reach what your policies allow. The service_role key and the new secret keys are the ones that must stay on a server.

Does Lovable check RLS for me?

Partly. Lovable's Quick scan flags tables without row-level security and rules that let everyone through, and the Deep scan looks for users who can reach data that is not theirs. Lovable still says you are responsible for your app's security and suggests a professional review for apps that handle sensitive data.

How much does a pentest for a vibe-coded app cost?

Our published starting prices are $250 for a scan, $500 for manual testing of common exploits and $2,500 for an in-depth manual pentest. The final figure follows a written scope, and the tiers are on our security audit page. Prices across the market vary with the number of roles, endpoints and retests, which our cost guide breaks down.

Can I pentest my own app before launch?

You can run the self-checks on your own project, and you should. Test only systems you own or have written permission to test, and do it against a staging copy with test data where you can. A self-test is good at finding the obvious holes. It is weaker at chaining small issues together.

Want a second pair of eyes before launch?

Send us the app URL, the stack (Lovable, Bolt, Cursor, Supabase or something else) and what data it will hold, and we will tell you which checks you can do yourself and whether a paid test is worth it yet: Book a free 30-min assessment.

How this guide was made: Ramin Moradi researched and wrote it with AI assistance. Supabase, Lovable, OWASP and GitHub wording was checked against the linked pages on 11 November 2026 (Europe/Istanbul), as were the Crissy Field and Matt Palmer reports. The check order and the decision table are our own rule of thumb, not a Supabase or Lovable rule. Vendor docs change often, so re-read them before you rely on a specific setting.

Comments

Loading comments

Ready to get started?

If this page matches the job, send the brief. We will say no if it does not.