← All guides

How to Security Review Cursor-Generated Code

Updated 2026-10-14

AI editors like Cursor, Windsurf and Claude Code write a lot of code quickly, and most of it works. "Works" and "safe" are different things, though. The model optimizes for making the feature run, and security checks are exactly the kind of thing that gets dropped when it's trying to make an error go away.

You don't need to be a security engineer to catch most problems. You need a repeatable way to review what the AI wrote. This guide gives you one.

Review the diff, not the chat

The chat summary tells you what the AI meant to do. The diff tells you what it did. Before accepting a large change, look at the actual file changes, and pay extra attention to:

Commit in small steps so each diff is reviewable. A single "build the whole dashboard" change touching 40 files is hard to review well.

The seven things to look for

1. Secrets in code

Search every change for anything that looks like a key:

git diff --cached | grep -nE "sk_live|sk_test|sk-[A-Za-z0-9]{10,}|service_role|sb_secret_|whsec_|AKIA[0-9A-Z]{16}"

Also check for new NEXT_PUBLIC_ or VITE_ variables. Those end up in the browser. AI tools sometimes rename a secret to NEXT_PUBLIC_... to fix an "undefined" error in a client component. That's a leak. See exposed keys in NEXT_PUBLIC_ and VITE_.

2. Missing auth in server code

For every new route handler, Server Action or edge function, check the first few lines. There should be a session check before any data access. If there isn't, ask the AI to add one, or add it yourself. Patterns are in securing Next.js API routes with auth and Next.js Server Actions security.

3. Trusting IDs and roles from the client

Look for code that reads userId, ownerId, role or isAdmin from the request body, query string or form data. Identity must come from the verified session. This is one of the most common bugs in generated code, because it makes the feature work in a demo.

// Red flag
const { userId } = await req.json();

// What you want
const { data: { user } } = await supabase.auth.getUser();

4. Weakened database rules

Check migrations for:

These often appear right after a "permission denied" error. The Supabase RLS checklist and Firebase security rules guide explain the fixes.

5. Service role or admin SDK where it isn't needed

If the AI switched from the regular Supabase client to the service role client "to fix permissions", RLS is now bypassed for that code path. Ask why. Usually the right fix is a correct policy, not a more powerful key.

6. Unsafe handling of input

Look for:

// Red flag: SQL injection
await sql.unsafe(`select * from posts where slug = '${slug}'`);

// Safer: parameterized
await sql`select * from posts where slug = ${slug}`;

7. Payments and webhooks

Any code that grants paid access should be triggered by a verified webhook, not by a redirect to /success or a client-side call. Check that webhook handlers verify signatures with the raw body. See Stripe webhook signature verification in Next.js.

Check new dependencies

AI models sometimes suggest packages that are outdated, unmaintained, or don't exist at all. A made-up package name is a risk, because someone can publish a malicious package under that name. For every new dependency:

Use prompts that ask for security

Asking directly helps. After a feature is built, try a follow-up prompt such as:

Review the changes in this branch for security issues. For each API route and server action, confirm there is an auth check and that record access is scoped to the current user. Flag any secrets, any new NEXT_PUBLIC_ variables, any RLS changes, and any input that reaches SQL or HTML without validation. Don't change code yet; list the issues first.

Asking for a list before changes keeps the review readable. Then fix the issues one at a time.

Add a rules file

Cursor supports project rules (in .cursor/rules) that are included in the AI's context. A short security rule makes good patterns the default:

---
description: Security rules for this project
alwaysApply: true
---

- Never hardcode API keys or secrets. Read them from server-side env vars.
- Never put secrets in NEXT_PUBLIC_ or VITE_ variables.
- Every route handler and server action must verify the user with supabase.auth.getUser() before touching data.
- Take the user ID from the session, never from the request.
- Every new table must enable row level security and have owner-based policies.
- Never fix a permission error by using the service role key or `using (true)`.
- Validate request input with zod.
- Stripe webhooks must verify the signature using the raw request body.

Other editors have similar files (for example CLAUDE.md or AGENTS.md). The AI won't follow these perfectly, but it helps, and it gives you a checklist to review against.

Automate the boring parts

Manual review catches logic problems. Tools catch the repetitive ones every time:

A short review routine

For each AI-generated change before merging:

  1. Read the diff, focusing on server code, migrations and config.
  2. Run a secret search on the diff.
  3. Check each new endpoint for auth and ownership scoping.
  4. Check migrations and rules for weakened access.
  5. Verify any new dependencies.
  6. Test the feature logged out and as a second user.

It takes a few minutes per change, and it's much cheaper than finding out after launch.

Let a bot do the first pass

PreflightPR is built for this situation. It reviews AI-built repos for the issues above, including leaked keys, missing RLS, unprotected routes and unverified webhooks, and can open a pull request with fixes. Run a free scan on a public repo to see your launch score. It's an automated best-effort check, so keep reviewing the diffs yourself too.

Check your repo in about a minute

Paste a public GitHub URL and get a free launch score.

Run a free scan

More guides