Hardcoded API Keys in Bolt, Lovable & Cursor: How to Find and Remove Them - VibeDoctor 
← All Articles 🔒 Security Vulnerabilities Critical

Hardcoded API Keys in Bolt, Lovable & Cursor: How to Find and Remove Them

AI coding tools embed API keys directly in source code. Learn how to find hardcoded Stripe, OpenAI, and AWS keys before attackers do.

SEC-014 SEC-015 SEC-016

Quick Answer

Hardcoded API keys are credentials (Stripe, OpenAI, AWS, etc.) written directly into source code instead of loaded from environment variables. AI coding tools like Bolt, Lovable, and Cursor frequently embed keys in code to make things work quickly. Once pushed to GitHub, these secrets are exposed to anyone - and bots scan for them within minutes.

How Big Is the Hardcoded Secrets Problem?

In 2024, GitHub reported that over 12.8 million secrets were exposed in public repositories in a single year. That's API keys, database passwords, and private tokens - sitting in plain text. GitGuardian's 2024 State of Secrets Sprawl report found that 1 in 10 code authors exposed a secret in 2023.

For vibe-coded apps built with Bolt, Lovable, Cursor, or v0, the problem is worse. When you prompt "add Stripe payments" or "connect to OpenAI," the AI generates working code the fastest way it knows how - by putting the key right in the source file. It works. It deploys. And your secret key is now in your Git history forever.

According to Veracode's 2023 report, hardcoded credentials appear in 19% of all applications scanned. For AI-generated code, that number is estimated to be significantly higher because AI tools prioritize functionality over security practices.

What AI Tools Actually Generate

Here's a realistic example of what Bolt might produce when you ask it to "add OpenAI chat to my app":

// ❌ BAD - Hardcoded API Keys
import OpenAI from 'openai';
import Stripe from 'stripe';

const openai = new OpenAI({
  apiKey: 'sk-proj-abc123def456ghi789jkl012mno345pqr678'
});

const stripe = new Stripe(
  'sk_live_51ABC123DEF456GHI789JKL012MNO345PQR678STU',
  { apiVersion: '2024-06-20' }
);

// AWS credentials
const s3Client = new S3Client({
  region: 'us-east-1',
  credentials: {
    accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
    secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
  }
});

Every one of these keys is a live credential with real billing attached. An exposed Stripe secret key lets attackers process charges. An exposed OpenAI key racks up usage costs. An exposed AWS key can spin up servers or access S3 buckets.

Why Removing the Key From Code Isn't Enough

Here's the part most people miss: deleting the key from your code and pushing a new commit does not remove it. Git stores every version of every file. Anyone can run git log -p and find your old key in the commit history.

This is why VibeDoctor's secret detection runs Gitleaks across your entire Git history - not just the current codebase. Even if you removed the key months ago, it's still findable.

If a secret was ever committed:

  1. Rotate the key immediately - generate a new one in the provider's dashboard and revoke the old key
  2. Move to environment variables - use .env files locally and platform secrets in production
  3. Add .env to .gitignore - prevent future commits of secret files
  4. Consider rewriting history - use git filter-repo or BFG Repo Cleaner to remove the secret from all commits

The Correct Way to Handle Secrets

// ✅ GOOD - Environment Variables
import OpenAI from 'openai';
import Stripe from 'stripe';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY
});

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
  apiVersion: '2024-06-20'
});

// AWS - use IAM roles in production, env vars in dev
const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
  }
});

Then create a .env file (never committed to Git) and a .env.example (committed, with placeholder values):

# .env.example - commit this to Git
OPENAI_API_KEY=sk-your-key-here
STRIPE_SECRET_KEY=sk_live_your-key-here
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=us-east-1

Where Secrets Hide: The Full Checklist

Secret Type Pattern to Search Common in
AWS Access Keys AKIA followed by 16 chars Bolt, Cursor
Stripe Live Keys sk_live_ prefix Bolt, Lovable
OpenAI Keys sk- or sk-proj- prefix All AI tools
GitHub Tokens ghp_ or gho_ prefix Cursor, v0
Supabase Service Keys eyJhbG... (JWT format) Bolt, Lovable
Database URLs postgresql:// or mongodb+srv:// All tools
SendGrid Keys SG. prefix Cursor, Bolt
Private Keys -----BEGIN RSA PRIVATE KEY----- All tools

How to Scan Your Code for Hardcoded Secrets

Manual searching is unreliable - secrets come in many formats and can be buried deep in your codebase or Git history. Here's what works:

  1. Automated scanning: Tools like VibeDoctor (vibedoctor.io) automatically scan your codebase and Git history for hardcoded secrets using Gitleaks. It flags the exact file, line number, and commit where the secret was introduced. Free to sign up.
  2. GitHub Secret Scanning: If you're on a public repo, GitHub's built-in secret scanning can alert you. But it only works on public repos for free accounts.
  3. Pre-commit hooks: Install Gitleaks as a pre-commit hook to prevent secrets from being committed in the first place.
  4. Use platform secrets: Vercel, Netlify, Railway, and Render all support environment variables in their dashboard. Never rely on .env files in production.

NEXT_PUBLIC_ and VITE_ - The Sneaky Frontend Exposure

This is unique to vibe-coded apps. When AI tools build Next.js or Vite apps, they sometimes prefix secret keys with NEXT_PUBLIC_ or VITE_ to make them "work" on the client side. This means the key is bundled into your JavaScript and visible to anyone who opens browser DevTools.

Never put secret keys in client-side env vars. Supabase anon keys are designed to be public (with Row Level Security). Stripe publishable keys (pk_live_) are fine on the client. But secret keys, service role keys, and API keys with write access must stay server-side only.

FAQ

What if I already pushed a secret key to GitHub?

Rotate the key immediately in the provider's dashboard. Then remove it from your code, add it to .env, and use git filter-repo or BFG Repo Cleaner to scrub it from history. Simply deleting and re-committing is not enough.

Are Supabase anon keys safe to expose?

The Supabase anon key is designed to be public - it respects Row Level Security (RLS) policies. But the service_role key bypasses RLS entirely and must NEVER be exposed on the client or committed to Git.

Does Bolt or Lovable hardcode secrets?

Yes, frequently. When you provide API keys in the prompt or paste them into the editor, AI tools embed them directly in source code. Always replace hardcoded keys with process.env references before deploying.

How fast do bots find exposed keys on GitHub?

Automated scanners find exposed AWS keys within minutes of a public commit. GitHub reports that most exposed secrets are exploited within 1 hour. AWS credential exposure has led to six-figure cloud bills.

Which tool finds the most secret types?

Gitleaks (used by VibeDoctor's scanning pipeline) detects 100+ secret patterns including AWS, Stripe, OpenAI, GitHub, Slack, SendGrid, Firebase, and more - across your full Git history, not just the current code.

Scan your codebase for this issue - free

VibeDoctor checks for SEC-014, SEC-015, SEC-016 and 128 other issues across 15 diagnostic areas.

SCAN MY APP →
← Back to all articles View all 129+ checks →