Cursor and AI pair programming: the security mistakes that keep coming back
Cursor isn't an app generator like Bolt, Lovable, or v0 — it's a code editor with an AI agent that reads, edits, and writes directly into an existing project. The resulting risk is different: it's not a backend generated all at once without RLS, it's a series of small changes made in trust, some of which touch secrets without anyone reading them line by line.
The agent doesn't know your security intentions
When you ask the Cursor agent to "add Stripe integration" or "wire this route to the database", it produces code that works — that's its success criterion. Nothing stops it from pasting a key found in your .env straight into a client component because that's the shortest path to making the demo work, especially if the prompt doesn't explicitly specify where the code should run:
// a plausible suggestion from an agent optimizing for "it works"
// components/CheckoutButton.tsx (client-side file)
const stripe = new Stripe("sk_live_..."); // ❌ runs in the browserThe code compiles, the payment works in testing, and the secret key ships in the public JS bundle without any alert firing — the agent has no notion of "this variable must never reach the client" unless you tell it so.
A diff is easier to accept than to actually read
The agent in autonomous mode can chain changes across several files at once, with an "accept all" button. That's where secret-related changes most often slip through unnoticed: a renamed variable, a configuration example copied from a third-party service's docs with a real key instead of a placeholder, a .env file generated and then committed because the project's .gitignore didn't cover it yet at that point.
The fix
Specifically review diffs that touch authentication, payments, or configuration — not just skim for build errors. Confirm .env is in .gitignore before the very first commit, not after the fact:
# .gitignore — check this before the project's first commit
.env
.env.local
.env*.localA pre-commit hook that scans for known key patterns (sk_live_, AKIA...) before every push catches what a manual review sometimes misses. Details and other common patterns: Hardcoded API keys and secrets and Publicly exposed .env or .git.
Got a project evolving through Cursor prompts and already live? Scan it to check no secret slipped into the public JavaScript along the way.