The vibe coder security checklist
Most security disasters in vibe-coded apps come from the same dozen mistakes. AI editors are great at building features. Less great at catching the security stuff you forgot to ask about. This is what every Cursor, Lovable, Bolt, or v0 user should run through before pushing to production. No theory, no jargon. Just the things that bite.
- 01
Get API keys out of your code
The single most expensive mistake. Stripe keys, OpenAI tokens, AWS secrets, any of them sitting in your source files instead of an .env file is one push away from a compromised account. Bots scrape GitHub for new commits every few minutes.
Read the deep-dive: Exposed API keysPaste this into Cursor / Lovable / BoltFind every hardcoded API key or secret in this repo. Move each one to a .env file, replace the hardcoded value with process.env.WHATEVER, and add .env to .gitignore. Then tell me which keys I need to rotate at the provider.
- 02
Ignore the .env file
Even when secrets live in .env, that file still gets pushed if you forgot to add it to .gitignore. Check now, not after.
Read the deep-dive: .env file exposurePaste this into Cursor / Lovable / BoltAdd .env, .env.local, and .env.*.local to .gitignore. If any .env files are already tracked by git, run git rm --cached on them and commit the change.
- 03
Put auth in front of every API route
Most AI-generated backends ship endpoints that anyone on the internet can hit. Some return user data. Some write to the database. All of them need a session check before they do anything sensitive.
Read the deep-dive: Unprotected API routesPaste this into Cursor / Lovable / BoltAudit every API route in this project. For each one, add a session check at the top that returns 401 if the user isn't signed in. Skip the obvious public ones like /api/health.
- 04
Stop user A from reading user B's data
Even with auth, if your endpoint says "give me /api/orders/42" and just trusts the 42, anyone can swap their order ID for someone else's. The real check is "is this order yours," not "are you logged in."
Read the deep-dive: Broken access controlPaste this into Cursor / Lovable / BoltFind every API route that reads a resource by id from the URL. Add an ownership check: confirm the resource belongs to the current user before returning it.
- 05
Force HTTPS
HTTP traffic is readable by anyone between your user and your server. Public Wi-Fi, hostile ISPs, anyone. On most modern hosts the fix is one config line.
Read the deep-dive: HTTPS enforcementPaste this into Cursor / Lovable / BoltAdd a redirect from HTTP to HTTPS in this app. If we're on Vercel or Netlify, also set a Strict-Transport-Security header so browsers remember.
- 06
Tighten your CORS policy
A wide-open CORS policy lets any website on the internet make authenticated calls to your API in the background. The fix is naming the exact domains you actually use.
Read the deep-dive: CORS misconfigurationPaste this into Cursor / Lovable / BoltFind the CORS config in this project. Replace any '*' or 'true' values with a list of the specific origins my app uses (production domain plus localhost for dev).
- 07
Validate every input
If a route accepts JSON, treat that JSON as hostile until you've validated it. Use Zod or a similar schema library. Don't trust the client to send what you expect.
Read the deep-dive: API input validationPaste this into Cursor / Lovable / BoltFor each API route in this project, add a Zod schema for the request body and parse it before doing anything else. Return a 400 on parse failure with the validation errors.
- 08
Hash passwords with bcrypt or argon2
If you store user passwords yourself and they aren't hashed with bcrypt or argon2, a database leak hands attackers every account. Plain SHA-256 doesn't count.
Read the deep-dive: Password hashingPaste this into Cursor / Lovable / BoltFind where I store user passwords. Replace whatever hashing I'm using with bcrypt (cost 12 minimum) and update the login flow to use bcrypt.compare.
- 09
Verify Stripe webhook signatures
A Stripe webhook handler that skips signature verification can be called by anyone claiming any event. Free Pro subscriptions for everyone.
Read the deep-dive: Stripe webhook securityPaste this into Cursor / Lovable / BoltIn my Stripe webhook handler, verify the stripe-signature header using stripe.webhooks.constructEvent and the STRIPE_WEBHOOK_SECRET. Reject the request with 400 if verification fails.
- 10
Ship a privacy policy
Not security, but cheap to fix and required by every payment processor and ad network. Stripe, Google, Apple, and the GDPR and CCPA folks all want to see one before they let you go live.
Read the deep-dive: Missing privacy policyPaste this into Cursor / Lovable / BoltGenerate a basic privacy policy page for my app at /privacy. Cover what data we collect, why, who we share it with (Stripe, analytics), and how users can request deletion. Link to it from the footer.
This list catches roughly 80% of what trips up vibe-coded apps in production. If you want the rest caught automatically, run a Heimdall scan. We'll check everything on this list plus the ones you forgot to ask about.
