Heimdall Scan logo, AI security scanner for vibe coders
Heimdall ScanOpen Beta
Guide

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.

  1. 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.

    Paste this into Cursor / Lovable / Bolt
    Find 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.
    Read the deep-dive: Exposed API keys
  2. 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.

    Paste this into Cursor / Lovable / Bolt
    Add .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.
    Read the deep-dive: .env file exposure
  3. 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.

    Paste this into Cursor / Lovable / Bolt
    Audit 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.
    Read the deep-dive: Unprotected API routes
  4. 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."

    Paste this into Cursor / Lovable / Bolt
    Find 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.
    Read the deep-dive: Broken access control
  5. 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.

    Paste this into Cursor / Lovable / Bolt
    Add 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.
    Read the deep-dive: HTTPS enforcement
  6. 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.

    Paste this into Cursor / Lovable / Bolt
    Find 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).
    Read the deep-dive: CORS misconfiguration
  7. 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.

    Paste this into Cursor / Lovable / Bolt
    For 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.
    Read the deep-dive: API input validation
  8. 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.

    Paste this into Cursor / Lovable / Bolt
    Find 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.
    Read the deep-dive: Password hashing
  9. 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.

    Paste this into Cursor / Lovable / Bolt
    In 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.
    Read the deep-dive: Stripe webhook security
  10. 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.

    Paste this into Cursor / Lovable / Bolt
    Generate 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.
    Read the deep-dive: Missing privacy policy

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.