Example finding How it works Coverage PENTEST METHODOLOGY DOCS PRICING FAQ MCP CONTACT LOG IN SIGN UP →

Lovable vs Bolt vs Cursor: Same Spec, Three Apps, Three Security Profiles (2026)

We gave Lovable, Bolt.new, and Cursor the exact same one-paragraph spec - a freelancer invoice-tracking SaaS. Each built a working app. We scanned all three. The findings are different, the totals are different, and the failure modes are not what platform marketing pages would have you expect.

This is a controlled experiment. One spec, three platforms, three deployed apps, one scan. The numbers below are not aggregates from a corpus - they are findings from three specific apps, all generated and deployed in March 2026 from the same starting prompt.

The study shows that “is platform X secure” is a question with a structurally different answer for each platform, even when the spec is identical.

We publish it as a data study, not a league table, because ranking tools by total CVSS-ish bars without category context misleads buyers. Read the critical matrix and the failure-profile sections before the totals.

The spec

Verbatim, given as the first message to each platform’s generator:

Build a SaaS web app for freelancers to send invoices. Users sign up with email + password. Each user can create invoices with line items, tax, and a due date. Invoices can be marked sent, paid, or overdue. Users see a dashboard with the total outstanding amount and a list of recent invoices. Stripe integration to collect payment when the client clicks the invoice link. Use a backend so I can add features later.

We accepted the first deployable build on each platform. No follow-up prompts, no refactoring, no manual edits.

Results - total findings

Severity Lovable Bolt.new Cursor
Critical 4 3 1
High 6 9 4
Medium 11 7 9
Low 8 5 12
Total 29 24 26

Total counts are within noise of each other. The story is in the distribution.

Critical findings, side by side

# Finding Lovable Bolt.new Cursor
1 Missing RLS on invoices table yes n/a (no Supabase) n/a (no Supabase)
2 Missing RLS on users table yes n/a n/a
3 Stripe sk_live_ in frontend bundle no yes no
4 Supabase service-role JWT in bundle yes n/a n/a
5 OpenAI key in bundle (used for invoice description AI) no yes no
6 BOLA on GET /api/invoices/:id n/a (PostgREST) yes yes
7 BOLA on PATCH /api/invoices/:id yes (RLS gap) yes no

Three completely different failure profiles emerge from the same spec.

Failure profile by platform

Lovable

Concentration: database authorization. All four critical findings are RLS gaps. The Stripe integration is correct; Lovable consistently routes Stripe through Supabase Edge Functions and does not ship the secret key. The auth flow is correct; users are authenticated via Supabase Auth.

What fails is RLS on the tables Lovable’s generator created - invoices, users, line_items, and payments. None had policies. The dashboard shows them as RLS-disabled.

Modal failure mode. Permissive policy or policy missing entirely.

Single-line fix per table. Add using (auth.uid() = user_id) to a select policy on each.

Bolt.new

Concentration: secret handling. Bolt produced a frontend-only app with serverless functions - no Supabase, just Postgres via a connection string. The connection string ended up in the frontend bundle. The Stripe sk_live_ key, also in the bundle. The OpenAI key Bolt added for an “AI-generated invoice description” feature, also in the bundle.

The authorization on the API endpoints is mostly correct, but it is the only thing standing between the public bundle and full database access - and a connection string in the bundle bypasses the API entirely.

Modal failure mode. Secrets shipped to the browser via VITE_* environment variables.

Single-line fix per secret. Move the secret to a server-only variable, route the integration through a backend handler.

Cursor

Concentration: custom API authorization. Cursor produced the most architecturally clean app - Next.js with API routes, JWT-based auth, environment-variable secrets. The secrets are correctly server-only. The auth flow is correct.

What fails is the authorization logic in the API routes. Most route handlers fetch the resource by ID and return it without checking ownership. Two routes accept arbitrary fields in the update body, including fields that should be immutable.

Modal failure mode. Missing ownership check in route handlers.

Single-line fix per route. Add if (resource.user_id !== session.user.id) return new Response(null, { status: 404 }).

What this means for the “is X safe” question

The three apps produced from the same spec have:

  • Comparable total finding counts (24, 26, 29)
  • Three completely different concentrations of critical findings
  • Three completely different audit checklists for the builder

A founder reading “is Lovable safe” and getting a generic answer will not realize that the Lovable-specific audit is different from the Bolt-specific audit which is different from the Cursor-specific audit. Each platform’s safety posture is shaped by where it routes integrations and how it handles state - not by a generic “yes/no”.

The platform-specific safety reviews (Lovable, Bolt, Cursor) carry the per-platform fix lists.

CWE / OWASP profile per platform

The same total finding count, three completely different CWE distributions. Each platform’s “modal failure” maps to a different fix surface.

Platform Modal CWE family Modal OWASP Fix surface
Lovable CWE-862 Missing Authorization · CWE-863 Incorrect Authorization A01 Broken Access Control · API1 BOLA Supabase RLS policies on every table the generator added
Bolt CWE-798 Hard-coded Credentials · CWE-540 Sensitive Info in Source A02 Cryptographic Failures · A05 Security Misconfiguration Move every secret to server-only env; add a backend handler
Cursor CWE-639 Auth Bypass via Key · CWE-915 Mass Assignment A04 Insecure Design · API1 BOLA · API6 Mass Assignment Add ownership checks in API route handlers; allow-list update fields
All three (shared baseline) CWE-352 CSRF · CWE-770 No Rate Limit · CWE-693 Protection Mechanism Failure A05 Security Misconfiguration Platform-independent middleware: CSRF tokens, rate limit, security headers

The Lovable and Cursor profiles overlap on OWASP API1 (BOLA) but the layer differs - Lovable’s BOLA is in the database via missing RLS, Cursor’s is in the application via missing checks in the route handler. The fix per-finding is short in either case; the fix per-platform requires a checklist shaped to where the platform routes the data.

Pattern walkthroughs per failure profile

Each modal failure surfaced in this experiment has a companion pattern walkthrough that shows the bug on a live URL and walks the fix per stack:

What was the same

All three apps:

  • Allowed CSRF on state-changing endpoints (no platform added CSRF protection by default)
  • Shipped without rate limits on signup or login
  • Returned verbose error messages including stack traces in development mode (still on at deploy time)
  • Lacked HSTS headers
  • Lacked Content-Security-Policy headers

These five items are the platform-independent baseline failures of vibe-coded apps. They are not failures of one platform’s generator; they are failures of the entire category.

Why shared baseline failures persist

Generators optimize for interactive demos on localhost and preview URLs. Rate limits annoy demos. CSP breaks inline scripts and third-party embeds the model loves. Stack traces speed up the agent’s own debug loop. HSTS is invisible until you care about cookie flags and HTTPS downgrade - rare in a 20-minute build.

The industry fix is not “prompt better” alone; it is host defaults + CI gates that re-introduce baseline controls after generation. Until platforms ship secure-by-default headers and auth throttles, expect this cluster on every uncontrolled first deploy.

Methodology

Builds. Each app was created on a fresh trial account using the platform’s standard new-project flow. The full prompt above was the first and only message; we accepted the first deployable build. No iterations, no follow-ups, no manual edits. All three were built within a 48-hour window in March 2026.

Scan. Identical scan run against each deployed URL. The full VibeEval probe set (310 probes) ran with the same configuration on each.

Reproducibility. The prompt is reproducible. The artifacts are not - AI builders are non-deterministic. We expect any rerun to produce comparable but not identical findings; the failure-profile shape should hold across reruns even if individual counts shift.

Vendor outreach. Lovable, StackBlitz (Bolt.new), and Anysphere (Cursor) were notified 30 days before publication. Responses included where provided.

Calibration via gapbench equivalents. Each per-platform modal failure has a matched scenario on gapbench.vibe-eval.com that reproduces the same shape of bug independent of the specific apps in this experiment. This lets readers verify the detection (against the public benchmark) without relying on access to the specific deployed URLs of the experiment apps. Every detection that fired in this experiment also fires against its matched scenario, and is silent against ref0.

What we did not do. We did not attempt social engineering, physical access, or dependency confusion against the platforms themselves. We did not keep the apps online after the study window. We did not tune prompts toward insecure outcomes - the insecure outcomes were the defaults.

Scoring. Severity labels follow VibeEval’s internal rubric aligned with common-sense impact (cross-user PII = Critical, secrets in browser = Critical, missing headers = Low/Medium). Totals count distinct findings, not CVSS sums.

Reproduce on the public benchmark

The deployed experiment apps are not public - they were built on platform trial accounts, and re-publishing the URLs would surface user PII the platforms generated as test data. The reproducibility anchor for this study is the matched gapbench scenarios:

Profile in the experiment Equivalent gapbench scenario What reproduces
Lovable - RLS gaps on invoices/users/line_items/payments supabase-clone RLS off, permissive policy, partial coverage all on one app
Lovable - service-role JWT in bundle supabase-clone, config-leak Service-role JWT inlined
Bolt - Stripe / OpenAI / connection-string in bundle indie-saas Stripe sk_live_ + secrets stack
Cursor - BOLA on GET / PATCH multi-tenant-saas, fintech-app Cross-account read and write
Shared baseline - no rate limit, no CSRF, no HSTS auth-system Authentication surface with the platform-independent gaps
Clean reference for false-positive calibration ref0, ref-rls Same scan; no findings

Reading the severity matrix correctly

Totals of 24 / 26 / 29 invite a false ranking (“Bolt wins”). That ranking is wrong for three reasons:

  1. Criticals are not equal. Four open-database criticals (Lovable) can expose every invoice and user email in one curl. Nine “high” secret findings (Bolt) may include overlapping keys. One BOLA critical (Cursor) may still dump all invoices via IDOR automation.
  2. n/a is not a free pass. Lovable has no “Stripe in bundle” critical because Stripe was server-routed - good - while still failing the data plane. Cursor has no Supabase RLS critical because it never used Supabase - it failed authorization in API routes instead.
  3. Low findings accumulate compliance pain. Missing HSTS and verbose errors rarely trend on Twitter; they still fail enterprise questionnaires.

Score products by modal failure + time-to-fix, not by total bars on a chart.

Time-to-fix estimates from this run

Approximate engineer effort to clear criticals only after the scan (experienced full-stack, not including product redesign):

Platform Critical theme Estimated fix time Verification
Lovable RLS on 4 tables + service role removal 1–3 hours Anon curl empty; two-user tests
Bolt Relocate 3 secrets + kill connection string in client 2–4 hours Bundle grep clean; secrets server-only
Cursor Ownership checks on invoice GET/PATCH (+ mass assign) 2–5 hours User B 404 on A’s ids

Shared baseline (rate limit, CSRF, headers) adds half a day to a day across all three if done properly with middleware and config - usually skipped in MVP panic.

What the invoice domain forces into the open

The freelancer-invoice spec was deliberate: it requires auth, multi-row CRUD, money, and a third-party payment provider. Toys like “todo list” under-test generators. Invoices create:

  • Tables an attacker would target (amounts, client emails)
  • A payment trust boundary (Stripe)
  • Status fields (paid, overdue) attractive for mass assignment
  • Dashboard aggregates that tempt over-fetch without scoping

If your product is less sensitive, you may see fewer criticals - but the routing of risk (RLS vs secrets vs route authz) still tracks the platform’s architecture defaults.

Secondary findings

Beyond the critical table, the scan noted recurring mediums:

  • Verbose Supabase/PostgREST errors leaking schema hints (Lovable)
  • OpenAPI / REST schema exposure aiding table discovery (Lovable)
  • Missing security headers on all three hosts
  • Login without rate limit enabling stuffing (all three)
  • CSRF-ish cookie patterns where cookie sessions existed without anti-CSRF (Cursor more than others)
  • Client-side-only route guards for “sent invoices” views (all three)

These did not change the headline profiles but would matter in a customer security review.

Threat-model mapping

Attacker goal Lovable path Bolt path Cursor path
Dump all invoices Anon REST select Use leaked DB URL or BOLA BOLA on GET
Steal payment capability Abuse Edge Function if mis-authed Use sk_live_ from bundle Hit API with user session + BOLA
Become “paid” without paying Forge row / status if writes open Replay or fake Stripe if webhook weak Mass assign status fields
Account takeover Auth config + session issues Same + secret-rich bundle aids pivot Same + API authz gaps

Different paths, same business impact: fraud and PII loss.

Limits of a single-spec experiment

  • One prompt, one build each - generators are stochastic; a second run might move a medium to high.
  • March 2026 generators - platform updates can shift defaults (we re-run quarterly).
  • Expert operators might prompt better - this study measures default first ship, not best-possible use.
  • Scanner coverage - 310 probes are broad; exotic business logic may need human pentest.
  • No mobile clients - only web deploys.

Still, the profile shape (RLS vs secrets vs handler authz) has been stable across our wider corpus, not only this trio.

Practical checklist derived from the study

If you build with Lovable: every table, every command, RLS; Storage; never service role in client; rescan after each schema prompt.

If you build with Bolt: treat every VITE_ as public; payments and AI keys only on server; audit functions for auth; grep bundles in CI.

If you build with Cursor (or any IDE agent): invent no magic - add ownership checks and allowlists on every route; write tests user A/B; do not trust “clean architecture” aesthetics.

If you build with any of them: rate limits, headers, CSRF strategy, webhook signatures, no stack traces in prod.

Vendor responses

[Reserved for vendor responses received during the disclosure window. None received as of publication. We will append responses below as they arrive.]

Citations

VibeEval. Lovable vs Bolt vs Cursor: Same Spec, Three Apps, Three Security Profiles. May 2026. https://vibe-eval.com/data-studies/lovable-bolt-cursor-same-spec/

What “same spec” experiments measure

Holding product requirements constant and varying generators surfaces systematic security gaps rather than one-off mistakes. Readers should replicate with their own prompts and scanners - treat published figures as directional unless methodology is fully open.

Builder takeaway

Tool ranking by security alone is unstable; process ranking (scan gates, dual-user tests) predicts outcomes better.

Prompt text as a controlled variable

We deliberately kept the prompt product-only: invoices, Stripe, dashboard, “use a backend.” We did not add “enable RLS,” “never put secrets in the client,” or “add ownership checks on every route.” Those instructions improve real projects - and would have confounded the experiment. The question was default first ship under founder product pressure, not expert-secured best case.

Follow-up (planned): same platforms plus a one-paragraph security addendum; measure delta in criticals. Until then, treat this study as a default-path benchmark.

Invoice abuse cases we exercised

Abuse Lovable Bolt Cursor
List all freelancers’ invoices Succeeded (RLS off) Partial via BOLA + secrets Succeeded via BOLA GET
Mark another user’s invoice paid Succeeded where writes open Succeeded via BOLA PATCH Ownership blocked PATCH; GET still open*
Extract Stripe secret N/A (server-routed) From bundle N/A (server env)
Extract DB connection string N/A From bundle N/A
200 failed logins without lockout All three All three All three

*Inconsistent authz across sibling handlers is common when agents patch one route and not the other.

Architecture of the three builds

Lovable: Browser React → supabase-js (anon + user JWT) → PostgREST/Auth/Storage → Postgres with RLS off on core tables; Edge Function → Stripe (secret server-side). Secret placement good; data plane open.

Bolt: Browser Vite SPA with VITE_* inlined secrets (Stripe, OpenAI, DB URL) → partial serverless authz → Postgres. Secret placement is the modal failure.

Cursor: Browser Next.js → API routes with JWT present → handlers fetch by id without owner check → server-only env for Stripe/OpenAI. Secrets good; handler authz fails.

Totals converge; fix surfaces diverge: Lovable needs SQL policies, Bolt needs env/bundle hygiene, Cursor needs dual-user handler tests.

Statistical humility (n=3)

Three deploys cannot support “platform X is 33% worse.” What n=3 supports: existence of each modal failure under one product prompt; proof that total-count rankings mislead; a methodology others can rerun quarterly; alignment with larger corpora (2026 benchmark, RLS atlas).

When vendors cite this page, demand the critical matrix - not a bar chart of totals.

Agency briefing language

Do not say “we avoid Lovable because of the study.” Say: whatever builder you used, we test three layers - database policies, secret placement, API ownership. This study shows each popular builder tends to fail a different layer first, so our checklist is layer-complete, not brand-based. Then attach the 48-hour hardening lists from Bolt vs Lovable security.

Scanner calibration

All three experiment apps and gapbench equivalents used the same 310-probe config. Supabase OpenAPI discovery fires on Lovable-shaped apps; VITE_ secret patterns are Bolt-weighted; Next.js route BOLA is Cursor-weighted; shared probes cover rate limit, HSTS, verbose errors. ref0 stayed clean - profile differences are signal, not host bias.

v2 protocol wishlist

  1. Three builds per platform (median criticals).
  2. Export + rescan after an “add teams” follow-up (longitudinal Lovable study).
  3. Blind second-reviewer severity labels.
  4. Time-to-first-critical from deploy (related).
  5. v0 + custom backend arm once artifact shape is normalized.

Reproduce dual-user invoice test

# Custom API (Bolt/Cursor shape)
curl -s -X GET "$API/invoices/$ID" -H "Authorization: Bearer $B_TOKEN"
curl -s -X PATCH "$API/invoices/$ID" \
  -H "Authorization: Bearer $B_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status":"paid"}'
# Expect 403/404

# Lovable / PostgREST shape
curl -s "$SUPA/rest/v1/invoices?id=eq.$ID&select=*" \
  -H "apikey: $ANON" -H "Authorization: Bearer $B_JWT"

Ship this script in every freelancer-SaaS PR template regardless of generator.

Line-item and tax edge cases (why the domain matters)

The invoice spec forced generators to model:

  • Header row (invoices) plus child rows (line_items)
  • Money fields (amount, tax, currency)
  • Lifecycle status (draft, sent, paid, overdue)
  • A third-party payment provider

Child tables without RLS (or without ownership via parent join) are a classic AI miss: parent locked, line items open. Status fields invite mass assignment (paid without Stripe). Tax and currency fields invite client-side price trust.

Any product with parent/child CRUD + money should expect the same three-platform split we observed: policy layer vs secret layer vs handler layer.

What “first deployable build” excluded

We did not:

  • Ask the model to “make it production ready”
  • Run a second prompt pass (“add security”)
  • Manually edit generated files
  • Choose the “best of N” samples from multiple attempts

That is stricter than how some power users work and closer to how non-experts ship. Power users who iterate security prompts will score better - and should still run the dual-user script, because models still skip WITH CHECK and ownership on sibling routes.

Stripe integration quality notes

Platform How Stripe was wired Secret placement Webhook quality (this build)
Lovable Edge Function Server secret Partial - verify signatures in your hardening pass
Bolt Mixed client/server Secret in bundle Unreliable if secret client-side
Cursor API route Server env Handler present; still verify signature + raw body

Payment security is not “use Stripe” - it is server secrets + signed webhooks + no client paid writes. See Stripe webhook trust.

How to cite this study without misuse

Fair: “Under a single product-only prompt, three popular AI builders produced apps with similar finding totals but different critical failure modes (RLS vs secrets vs route authz).”

Unfair: “Bolt is more secure than Lovable because it had fewer total findings.”

Fair for procurement: “Regardless of builder, require dual-user tests, secret classification, and a live scan before user PII.”

Include the methodology date (March 2026 builds, May 2026 publication) so readers account for generator drift.

Quarterly re-run plan

  1. Same verbatim prompt.
  2. Fresh trial accounts.
  3. Same 310-probe config (+ changelog if probes added).
  4. Publish delta table: criticals by category, not only totals.
  5. Update gapbench mapping if modal failures shift.

Subscribe via the data-studies index for re-run posts. Until then, treat profiles as directional defaults, not eternal rankings.

Appendix: finding-count raw table (this run)

Category Lovable Bolt Cursor
Critical 4 3 1
High 6 9 4
Medium 11 7 9
Low 8 5 12
Total 29 24 26

Critical themes (repeat for skimmers): Lovable = data plane (RLS + one service-role leak); Bolt = secrets in client; Cursor = incomplete ownership on API routes. Shared baseline failures (rate limit, CSRF, HSTS, verbose errors) are excluded from the “modal” story but counted in totals.

RUN IT YOURSELF

Each scenario below is live on the public benchmark. The commands are copy-paste ready. Outputs may evolve as we tune the scenarios; the bug stays.

Lovable-shaped failure - RLS off on invoices
curl -s 'https://gapbench.vibe-eval.com/site/supabase-clone/rest/v1/invoices?select=*' -H 'apikey: ANON_KEY'
expected 200 with every invoice - modal Lovable failure: missing policy on a generator-added table
Bolt-shaped failure - Stripe sk_live_ in bundle
curl -s https://gapbench.vibe-eval.com/site/indie-saas/ | grep -oE 'sk_(live|test)_[A-Za-z0-9]{20,}'
expected Stripe secret key inlined via VITE_*; modal Bolt failure
Cursor-shaped failure - BOLA on PATCH /invoices/:id
curl -s -X PATCH https://gapbench.vibe-eval.com/site/multi-tenant-saas/api/projects/1 -H 'Authorization: Bearer USER_B_TOKEN' -d '{"name":"hijacked"}'
expected 200 with mutation accepted; modal Cursor failure - clean architecture, missing ownership check
Shared baseline failure across all three - no rate limit on auth
for i in $(seq 1 200); do curl -s -X POST https://gapbench.vibe-eval.com/site/auth-system/api/login -d '{"email":"x@y.z","password":"wrong"}' & done; wait
expected 200 throughput - no rate limit; the platform-independent failure all three share
Clean control - ref0 produces nothing across the same scans
curl -s -I https://gapbench.vibe-eval.com/site/ref0/
expected All probes clean - confirms the platform-specific findings are not scanner noise

Common questions

Is one platform more secure than another based on this study?
No platform produced a clean app from the prompt. Each has a distinct failure profile - Lovable concentrates risk in Supabase RLS, Bolt in frontend secret handling, Cursor in custom API authorization. The takeaway is not 'use platform X' but 'know what platform X tends to skip and audit accordingly'.
Why these three platforms and not Replit or V0?
Replit and V0 produce fundamentally different artifact shapes - Replit is a hosted runtime with project-level configuration, V0 is component-only and requires a separate backend. Comparing apples to apples requires picking platforms that produce the same artifact: a deployable web app from a single prompt. Lovable, Bolt, and Cursor all do that. We will run the broader cross-platform comparison in a follow-up using a wider spec.
Was the prompt the same for all three platforms?
Verbatim, copy-pasted. The full prompt is in the methodology section. We made no platform-specific adjustments and accepted the first deployable build each platform produced. We did not iterate, refactor, or fix anything before scanning.
Will the result be the same if I run it tomorrow?
Probably not exactly the same. AI builders are non-deterministic and update their generators continuously. We will rerun the experiment quarterly and publish the diff. The methodology is fully reproducible - you can rerun it yourself with the same prompt.
Did you tell the platforms in advance?
No. The apps were built using normal trial accounts. We notified each platform vendor of the findings before publication and gave them a 30-day window to comment. Their responses (where provided) are at the bottom of this page.
Where can I see equivalent failure shapes on a public benchmark?
Each per-platform modal failure has a matched gapbench scenario. Lovable-shape: https://gapbench.vibe-eval.com/site/supabase-clone/. Bolt-shape: https://gapbench.vibe-eval.com/site/indie-saas/. Cursor-shape: https://gapbench.vibe-eval.com/site/multi-tenant-saas/. Each is curl-reproducible and the detection that fires there is the same detection that fired in this experiment.
How can the totals be similar but the profiles different?
Because total finding count is a poor proxy for security posture. Each platform routes integrations differently - Lovable through Supabase Edge Functions, Bolt through frontend-only patterns, Cursor through Next.js API routes - and each routing concentrates risk in a different layer. The total can be flat across three platforms while the *category* of vulnerability and the *fix surface* are completely disjoint.
What CWE / OWASP categories did the experiment surface?
Lovable findings clustered in CWE-862 / CWE-863 (RLS off, permissive policy) - OWASP A01 / API1. Bolt findings clustered in CWE-798 / CWE-540 (hard-coded credentials, sensitive info in source) - OWASP A02 / A05. Cursor findings clustered in CWE-639 / CWE-915 (auth bypass via key, mass assignment) - OWASP A04 / API1 / API6. The shared baseline failures (no CSRF, no rate limit, no HSTS) map to CWE-352, CWE-770, A05.

Run the same scan on your app

We used one methodology across tools. Apply that same probe to your deploy and see where you sit.

14-day free trial · No credit card · Cancel anytime

RUN COMPARABLE SCAN