Accesseon is now part of Stackproof, our new trust, security, and compliance platform for vibe-coded apps.Learn more β†’Your Accesseon subscription and scans are unchanged.
← All posts
Β·4 min readΒ·

The vibe-coding security checklist - 8 things Lovable, Bolt, and Cursor don't warn you about

Your AI coder just shipped an app. Here are the eight failure modes that plaintiff lawyers, security researchers, and your future self will find first.

securityvibe-codingsupabaserls

Before you keep reading - run a free scan on your own site.

See how many of the violations in this post actually apply to you. 30 seconds.

Free scan

Your AI coder ships fast. It does not ship safely. The default output of Lovable, Bolt, Cursor, Claude Code, and Replit Agent passes the happy path and leaks on the boring edge. Here are the eight failure modes we see repeatedly in production vibe-coded apps, in order of how often they turn into public incidents.

1. Supabase Row Level Security off by default

This is the single most common mistake and it took down 170+ Lovable apps in CVE-2025-48757. The pattern: developer creates a profiles table, ticks "enable RLS" in the Supabase dashboard... but never writes a policy. The effect is identical to leaving RLS off: the anon key reads every row. Your customer data is now on the public internet.

The check: From a fresh browser, with no session cookies, hit https://YOUR-PROJECT.supabase.co/rest/v1/profiles?select=*&limit=1 using your anon key. If it returns rows, you have a leak. Every table with PII or workspace-scoped data needs an explicit policy keyed to auth.uid().

2. Service-role key in the client bundle

Second-most-common. The Supabase dashboard labels service_role with a big red warning, but Lovable auto-generated templates used to hardcode it in a shared supabaseClient.ts for "convenience." If anyone ever imported that from a client component, the key shipped to every browser that loaded the app.

The check: curl YOUR_SITE | grep -o 'eyJ[A-Za-z0-9_-]\+\.eyJ[A-Za-z0-9_-]*service_role[A-Za-z0-9_-]*\.[A-Za-z0-9_-]\+'. If anything returns, rotate the key now.

3. OpenAI / Anthropic / Stripe keys in NEXT_PUBLIC_* env vars

Same pattern, different key. Next.js env vars prefixed with NEXT_PUBLIC_ get inlined into the client bundle at build time. Developers grep-replace "NEXT_PUBLIC" into every env var when debugging, and forget to undo it. Six months later a security researcher gets a notification from OpenAI that your key has been used for 200,000 chat completions from a Russian IP.

The check: Search your codebase for NEXT_PUBLIC_(OPENAI|ANTHROPIC|STRIPE|RESEND|PADDLE)_ and remove any hits. API keys belong in server-only env vars. Any key that ever shipped to a client must be rotated immediately.

4. CORS wildcard with credentials

Vercel templates occasionally ship with Access-Control-Allow-Origin: * on API routes. That alone is fine; combined with Access-Control-Allow-Credentials: true it becomes a vector for attacker-controlled sites to read authenticated responses from your origin. Chrome's CORS enforcement blocks the literal combo, but many proxies rewrite it in subtle ways and enough customers still ship it that automated scanners see it daily.

The check: curl -i -H "Origin: https://evil.example.com" YOUR_SITE/api/some-route. If you see both ACAO echoing your fake origin and Access-Control-Allow-Credentials: true, fix your CORS config.

5. /admin or /api/admin reachable without auth

Lovable scaffolds sometimes ship with a debug admin page behind a boolean env flag. When the flag is unset (which is the default), some frameworks render the admin page for anyone. Same story for /api/debug dumps.

The check: for p in /admin /api/admin /api/debug /debug; do curl -s -o /dev/null -w "%{http_code} $p\n" YOUR_SITE$p; done. Anything returning 200 is either intentional (fine) or a bug (not fine).

6. .env / .git/config served by the dev server

If your hosting provider serves the deploy root directly, .env and .git/config can leak. Railway and Vercel mostly get this right out of the box, but self-hosted containers behind Nginx frequently do not.

The check: curl YOUR_SITE/.env and curl YOUR_SITE/.git/config. Either returning 200 means your entire secrets store is reachable from the public internet.

7. No rate limit on signup / login

AI-generated code almost never adds rate limiting to auth endpoints. An attacker can enumerate valid emails via signup response timing, or brute-force passwords until the database locks legit users out. Plaintiff firms running ADA-inspired bots have started pivoting to credential-stuffing as a fringe benefit.

The check: Hit /api/auth/login or /api/signup 20 times in 2 seconds. If no 429 comes back, you need a rate limiter. Redis + a token bucket is 30 lines of code.

8. No security.txt

Not a bug, but a signal. RFC 9116's /.well-known/security.txt tells researchers how to report a vulnerability. Without it they often don't report at all - they just go public. The EU Product Liability Directive (enforceable December 2026) expects a documented disclosure channel as baseline product-maker diligence.

The check: curl YOUR_SITE/.well-known/security.txt. If it 404s, create a file pointing at a contact email. Takes five minutes.

The pattern

All eight of these are things your AI coder should know about, but it doesn't because it doesn't run your code in production. Stackproof runs the scan every time you push. We don't pretend to catch every business-logic bug ever written, but we do catch the boring, public-incident-making ones in the list above.

Run a free scan: the passive security probe covers items 2 through 8 on every scan with no credentials required. For item 1 (Supabase RLS), paste your anon key into the optional advanced field on the scan form. Service-role keys are rejected at the input.

Still reading?

Run the scan on your own site now

30 seconds. No signup. Shows exactly which violations on this post apply to you.

Start free scan