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

Secure your Bolt.new app

Bolt.new is fantastic for going from "idea" to "deployed prototype" in fifteen minutes. The "deployed" part is where it gets dangerous. The starter templates ship with example keys, the generated endpoints rarely have auth, and the one-click Netlify deploy pushes the lot straight to a public URL. If you're past the prototype stage, run through this before another deploy.

  1. 01

    Strip example keys from the starter template

    Bolt's templates include placeholder values like "your-stripe-key-here." Sometimes they also include real example tokens that look fake but actually work (typically test-mode keys from sandbox accounts). Strip them all before you commit.

    Paste this into Cursor / Lovable / Bolt
    Grep this project for any string that looks like an API key (sk_, pk_, AIza, ghp_, eyJ, sb-, AKIA). Replace each one with process.env.WHATEVER or import.meta.env.VITE_WHATEVER as appropriate. Tell me which ones I need to set in production.
    Read the deep-dive: Exposed API keys
  2. 02

    Move env vars to the Netlify dashboard

    The Bolt-to-Netlify pipeline doesn't always carry your .env over. Even when it does, the safer pattern is to set production secrets in the Netlify dashboard so they never touch your repo. Local .env keeps dev values; production reads from the host.

    Paste this into Cursor / Lovable / Bolt
    List every env var this project reads. For each one, tell me whether it's a public client-side value or a server-side secret. Then give me the exact commands or dashboard steps to set the secrets in Netlify production.
    Read the deep-dive: .env file exposure
  3. 03

    Tighten CORS before deploying

    Bolt's scaffolded endpoints often use the maximally permissive CORS config (Access-Control-Allow-Origin: *) because it works in every browser and never blocks development. In production, that means any website can call your API in the background using a logged-in user's cookies.

    Paste this into Cursor / Lovable / Bolt
    Find every CORS config in this project. Replace any `*` or `true` with a list containing exactly my production domain and (optionally) http://localhost:5173 for dev. Set Access-Control-Allow-Credentials to true only if I actually use cookies cross-origin.
    Read the deep-dive: CORS misconfiguration
  4. 04

    Add auth to every Bolt-generated endpoint

    "Add a route that returns user data" usually comes back as a route that returns user data to anyone who asks. Bolt skips the auth check more often than it adds it. Read the diff specifically for `if (!session)` or your framework's equivalent.

    Paste this into Cursor / Lovable / Bolt
    Audit every API route in this project. For each one, confirm there's an auth check that returns 401 when the user isn't signed in. List any routes missing the check and add one.
    Read the deep-dive: Unprotected API routes
  5. 05

    Check ownership in resource-by-id handlers

    Same problem as Cursor here: Bolt will happily write `db.from('orders').select().eq('id', req.params.id)` without checking the order belongs to the caller. Logged-in user, any ID, your data.

    Paste this into Cursor / Lovable / Bolt
    Find every route that fetches a resource by id from the URL. Add an ownership check that verifies the resource belongs to the current session's user. Return 403 on mismatch.
    Read the deep-dive: Broken access control
  6. 06

    Rate limit before you go public

    Prototypes don't need rate limits. Public URLs do. Without limits, your free-tier hosting and any provider quotas (OpenAI, Twilio, SendGrid) get drained by a single curl loop.

    Paste this into Cursor / Lovable / Bolt
    Add rate limiting to the public-facing endpoints in this project. Use Vercel or Netlify Edge Middleware, or a Redis-backed limiter like Upstash. Cap at 60 requests per minute per IP for general endpoints and 5 per minute for auth endpoints.
    Read the deep-dive: API rate limiting
  7. 07

    Verify Stripe webhooks

    If Bolt scaffolded Stripe for you, the webhook handler may not verify the signature. That's a paid-feature unlock for anyone willing to send a POST request.

    Paste this into Cursor / Lovable / Bolt
    In my Stripe webhook handler, verify the stripe-signature header using stripe.webhooks.constructEvent and STRIPE_WEBHOOK_SECRET. Reject the request with 400 if verification fails.
    Read the deep-dive: Stripe webhook security
  8. 08

    Force HTTPS and set HSTS

    Netlify gives you HTTPS for free, but the redirect from HTTP isn't always on for custom domains. Same for the HSTS header. Flip both, then make sure your cookies are Secure.

    Paste this into Cursor / Lovable / Bolt
    Add an HTTP-to-HTTPS redirect for this Netlify app. Add a Strict-Transport-Security header with max-age=31536000 and includeSubDomains. Set Secure and SameSite=Lax on any auth cookies.
    Read the deep-dive: HTTPS enforcement

Bolt makes the first deploy feel free. The second deploy is the one that hurts, once real users find your app and the bills come in. Heimdall checks all eight of these issues plus the rest in under a minute, so it's worth running once after your first proper deploy.