Checklist
Vibe coding security checklist: 47 checks before you ship
A practical vibe coding security checklist for apps built with Lovable, Cursor, Bolt, Claude Code or Codex: secrets, auth, ownership checks, Supabase RLS, payments, headers and what you can automate.
AI coding tools build what you ask for. They rarely add what you did not ask for: ownership checks, rate limits, a strict CSP, or a rule that keeps the service-role key on the server. The app works, so it looks finished. This vibe coding security checklist covers the gaps that show up again and again in AI-built apps.
Work through it in order on an app you own. Each section says which checks a scanner can automate and which need a quick manual test with two accounts. Mark every item Pass, Fail or Not applicable; an untested item is not a pass.
1. Secrets and API keys
Leaked keys are the fastest way to lose a database or a payment account. Check the repository and the built JavaScript, not only the current .env file. Automated: the GitHub repo scan flags committed .env files, Supabase secret and service-role keys, Stripe, OpenAI, AWS and GitHub tokens, private keys, hardcoded secrets and secret-looking public variables, without showing the value.
- No .env file, private key or database URL is committed, including in Git history.
- No secret uses a public prefix such as NEXT_PUBLIC_, VITE_ or REACT_APP_.
- Supabase secret (service-role), Stripe secret and OpenAI keys are only read in server code.
- Any key that was ever committed has been rotated, not just deleted.
- .gitignore covers .env* and GitHub push protection is on.
2. Authentication
Use the auth provider your stack ships with instead of a hand-rolled login. Then check the edges AI tools tend to skip.
- Email verification is required before an account can use paid or shared features.
- Login, signup and password reset are rate limited.
- Password reset tokens expire and work once.
- Logging out invalidates the session on the server, not only in the browser.
- Admin pages check the role on the server, not by hiding a link.
3. Ownership checks on every request
The most common serious bug in vibe-coded apps is an endpoint that loads a record by ID without checking it belongs to the signed-in user. Test it manually: sign in as user A, replay a request with user B's record ID, and confirm it is denied and B's data is unchanged. On paid plans, the AI logic review reads server routes in the repository and flags handlers that change data without an authorization check.
Where authority changes hands
4 · GitHub / CI → app release
Five boundaries: 1 Secrets, 2 Authorization, 3 Data access, 4 CI and releases, 5 Public app. Browser requests reach the public app edge, server routes, and database; CI publishes the release. Verify each boundary independently.
- Every read, update, delete and export checks ownership or tenant membership on the server.
- User and tenant IDs come from the session, never from the request body.
- Paid features are enforced on the server, not only in the UI.
- Invitations and role changes check the inviter's role.
4. Database rules (Supabase, Firebase)
If the browser talks to the database directly, the database rules are your authorization layer. Automated: the repo scan flags Supabase tables created in migrations without Row Level Security. Whether a policy is correct still needs a two-account test. The Supabase security checklist covers each step.
- RLS is enabled on every table in an exposed schema.
- No policy uses using (true) for data that belongs to a user or tenant.
- Storage buckets with private files are private and have owner policies.
- SECURITY DEFINER functions check auth.uid() inside.
- Firebase rules do not allow read or write: if true outside local testing.
5. Payments and webhooks
Payment code is where a small mistake becomes free usage or double charges.
- Stripe webhooks verify the signature before doing anything.
- Webhook handlers are idempotent, so a retried event does not grant credits twice.
- Plan and price come from your server or Stripe, never from the client.
- Access is granted after a confirmed payment event, not after a redirect to a success page.
6. Inputs, APIs and AI features
Treat every input as hostile, including text that will be sent to an LLM.
- Server-side validation on every API route, with a schema library such as Zod.
- Database access uses parameterized queries or an ORM, never string concatenation.
- File uploads check type and size and are stored outside the web root.
- CORS allows only your own origins, and never * together with credentials.
- Expensive endpoints, including AI calls, have per-user rate limits and spending caps.
- Prompts never contain secrets, and model output is never executed as code or SQL.
7. HTTPS and security headers
These are invisible in the UI and easy to forget. Automated: the website scan checks TLS, HTTPS redirects, HSTS and evaluates the Content-Security-Policy the way browsers enforce it.
- HTTPS everywhere, HTTP redirects to HTTPS, and HSTS is set.
- A Content-Security-Policy without unsafe-inline for scripts, or with nonces or hashes.
- Clickjacking protection with frame-ancestors or X-Frame-Options.
- X-Content-Type-Options: nosniff and a Referrer-Policy are set.
8. Exposed files and source maps
Build tools and hosting defaults can publish more than you meant to. Automated: the website scan requests known sensitive paths and confirms exposures by content, not just a 200 status.
- /.env, /.git/config and database dumps return 404.
- Production source maps are not public.
- Debug endpoints, GraphQL introspection and directory listings are off in production.
9. Cookies and sessions
Automated: the website scan checks every cookie it sees across crawled pages.
- Session cookies are Secure, HttpOnly and SameSite=Lax or Strict.
- Auth tokens are not stored in localStorage when a cookie session is available.
- Sessions expire and are rotated after login.
10. Dependencies and GitHub Actions
AI agents add packages and workflows quickly. Automated: the repo scan flags write-all workflow tokens, unpinned actions, pull_request_target workflows that run untrusted code, and known vulnerable dependencies.
- Every dependency is real and needed; remove packages the AI added and never used.
- npm audit or an equivalent runs in CI.
- Workflows declare least-privilege permissions and pin actions to a commit SHA.
- Agent and MCP configuration does not allow destructive commands without review.
11. Before every release
Security is not a one-time pass. A new prompt can undo an old fix. Scan the repository before merging, scan the live URL after deploying, and rescan after a fix to prove it reached production.
- Repository scan is clean of critical and high findings.
- Website scan of the production URL is clean of critical and high findings.
- Two-account ownership tests still pass on the release build.
- Errors and logs never print tokens or personal data.
Sources
Check your production site
See which of these issues are visible now.
ScanMySaaS checks the public surface and keeps the affected URL with every finding. Verify results before changing production.
Run a free scan