The 8-point checklist
Work through these in order — items 1 and 2 are the highest-severity findings in AI-generated apps and account for the most documented breaches.
-
Supabase Row Level Security
If your app uses Supabase (common in Lovable, Bolt, and v0 projects), every table in the
publicschema must have Row Level Security enabled with policies scoped to the authenticated user. The Supabase anon key ships in your client bundle — that is by design — but it grants data access according to your RLS policies. With RLS off or with a policy that allowsSELECTto everyone, the anon key is a full read (sometimes write) credential.In May 2025, security researcher Matt Palmer disclosed CVE-2025-48757 (CVSS 9.3 Critical): insufficient RLS policies in Lovable-generated Supabase projects allowed unauthenticated attackers to read or write arbitrary database tables. This is not a theoretical risk — it is the documented failure mode for this class of app.
How to check: In the Supabase dashboard, open Authentication → Policies. Every table should show "RLS enabled" and have at least one policy. For a definitive test, query the Supabase REST API with only the anon key and confirm you cannot read rows without authentication.
Sources: CVE-2025-48757 on NVD. Original research: Matt Palmer's disclosure (mattpalmer.io). Supabase RLS: Supabase RLS docs.
-
Secrets in the frontend bundle
AI tools frequently place all configuration in
.envfiles and then import everything in the frontend. In a Vite/React project, any variable prefixedVITE_is baked into the built JS bundle and is visible to anyone who views source. The Supabaseanonkey is safe in the bundle (it is public by design). The Supabaseservice_rolekey, Stripe secret key (sk_live_orsk_test_), or any third-party API token with write access is not — it must never reach the frontend.How to check: After building your project (
npm run build), grep the output:grep -r "service_role|sk_live|sk_test|secret" dist/Any match that is not the anon key or a non-sensitive config value is a leak to fix.
How to fix: Move secrets to a server-side function (Supabase Edge Function, Cloudflare Worker, Express route). Then rotate any secret that was in a previous build — it should be considered compromised.
-
Security headers
A freshly deployed Vite, Lovable, or Replit app typically serves no security headers. Missing
Content-Security-Policymakes XSS easier to exploit. MissingStrict-Transport-Securityallows HTTP downgrade on hostile networks. MissingX-Frame-Optionsenables clickjacking.How to check:
curl -sI https://yourdomain.com | grep -i "content-security|x-frame|x-content|strict-transport|referrer"Zero output means none of these headers are set.
The headers to add, in priority order:
Content-Security-Policy,Strict-Transport-Security(HSTS),X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy,Permissions-Policy.Set these at the hosting layer (Netlify
_headersfile, Vercelvercel.jsonheaders block, nginx config) so they apply to every response from the app. -
CORS policy
Access-Control-Allow-Origin: *on an API that reads theAuthorizationheader or authenticates via cookies is a credential-theft risk in certain browser contexts. AI-generated backends often start with a permissive wildcard CORS policy and leave it there. Review what your API does with theOriginheader and whether that policy is correct for what the API exposes.How to check: In your backend code, search for the CORS configuration. If you see
origin: '*'and the same API handles authenticated requests, tighten it to an explicit allowlist of your frontend origins. A wildcard is fine for truly public, read-only, unauthenticated APIs — not for authenticated ones. -
Exposed .env and config files
AI tools generate deployment configurations that often put the application directory and the web server document root in the same place. If the web server serves the project directory and
.envis in it, the file is directly downloadable. This is one of the fastest ways to lose every credential in a project at once.Common paths that scanners — and attackers — check:
/.env,/.env.local,/.env.production,/.env.backup,/.git/config.See the companion guide: How to Find Exposed .env Files on Your Website.
-
Dependency pinning
AI-generated
package.jsonfiles almost always use caret ranges (^), which meansnpm installin production can pull a different, newer version of a dependency than you tested with. If that version contains a vulnerability — or is itself a supply-chain compromise — you get it automatically.How to check: Run
npm auditand review the output. For production services, consider pinning exact versions inpackage-lock.jsonand committing the lock file.How to monitor ongoing: Enable Dependabot or
npm auditin your CI pipeline to catch new advisories as they are published. -
Authentication flows
Three specific weaknesses appear frequently in AI-generated auth implementations:
- No rate limiting on login or password-reset endpoints. Without a limit, these routes are open to credential stuffing. Add rate limiting at the edge or API layer.
- Password reset links that do not expire. A reset link left in someone's email indefinitely is an account-takeover risk. Set a short TTL (15–60 minutes).
- Email enumeration via different error messages. If "user not found" and "wrong password" produce different error messages, an attacker can enumerate valid accounts. Return the same message for both cases.
-
TLS configuration
Many hosting platforms (Vercel, Netlify, Replit) handle TLS automatically and correctly. Self-hosted or VPS deployments can end up with weak cipher suites, an incomplete certificate chain, or no HSTS. Weak ciphers like RC4, DES, or 3DES are deprecated; any server offering them is vulnerable to known attacks.
How to check: testssl.sh gives a comprehensive TLS analysis from the command line. pentes.io runs testssl.sh as part of every scan — the TLS section of the report covers certificate chain completeness, cipher suites, protocol versions, and HSTS.
See also: Why Is My SSL Certificate Not Trusted? — the most common TLS misconfiguration explained.
For Lovable builders specifically
If you built with Lovable, the highest-priority items are 1 (Supabase RLS), 2 (secrets in the bundle), 3 (security headers), and 5 (exposed .env files). The Lovable-specific guide walks through each of these against the exact stack Lovable generates: Is My Lovable App Secure?
For all vibe coders
Whether you built with Lovable, Bolt, v0, Replit, or another AI tool, the attack surface is shaped by the same patterns: fast generation, configuration decisions made at AI speed without a security review step, and deployment to a real public domain with real users. The vibe coders hub covers the full picture — platform-specific guides, what a non-destructive scan covers, and the Vibe Coder plan that makes it affordable to scan every deploy.
How to run all of these checks at once
Some items on this checklist require manual inspection; others can be automated:
- Automated by pentes.io scan: items 3 (security headers), 5 (exposed .env files), 8 (TLS configuration). The scan runs nuclei file-disclosure templates, a security-headers check, and testssl.sh — all non-destructive.
- Manual or requires code access: items 1 (RLS — you must inspect Supabase policies), 2 (bundle secrets — you must grep your build output), 4 (CORS — you must read your backend config), 6 (dependencies — run
npm audit), 7 (auth flows — you must test your endpoints).
A single pentes.io scan covers the public-surface checks in under five minutes. The manual items take longer but only need to be done once per significant architecture change.