VibeCheck Hub

The Cursor security checklist: checking the app Cursor built for you

Most Cursor security advice is about your source code privacy. This checklist is about the app Cursor built: keys, auth, inputs, with Cursor-ready fix prompts.

Search for "Cursor security" and almost everything you find answers a question you were not asking: whether Cursor is safe for a company's source code. Privacy modes, certifications, who can see your prompts. Useful if you are a CTO evaluating tools. Useless if you are the person who just built an app in Cursor and wants to know whether it is ready for strangers on the internet. This article is about the second question.

The distinction matters because the answers live in different places. Cursor's handling of your code is Cursor's job, and they document it themselves. The security of the app Cursor wrote is nobody's job until you make it yours. Nothing in the editor reviews what the agent shipped.

Why Cursor apps share failure modes at all

Unlike Lovable or Bolt, Cursor is an editor, not a platform. There is no single architecture to audit: you might have a Next.js app on Vercel, an Express API on a VPS, a Supabase backend, or all three. What Cursor apps share is not a stack but an author, and AI-generated code fails in consistent ways regardless of what it is generating. Veracode's research found security flaws introduced in roughly 45 percent of AI code generation tests, and an academic benchmark of AI-built apps found the same classes of issue across tools. So the checklist below is organized by what the AI did, not by what framework you picked.

The ten-minute version

If you ship today and have ten minutes, do these four in order:

  1. Search the repo for anything shaped like a key. Current files and git history both. Found one? Rotate it at the provider before doing anything else.
  2. Call one protected API route while logged out. Pick the most sensitive one. If it answers, you know what this afternoon is for.
  3. Change an ID in a URL that belongs to you. If you can see someone else's record, ownership checks are missing.
  4. Break something on purpose in production. A junk form submission. Stack traces in the response mean debug output is still on.

Clean on all four? Genuinely good sign. The full list below is the same idea, done properly.

1. Keys written straight into the code

When you ask Cursor to "connect Stripe", the fastest working version puts the key in the file, and Cursor optimizes for the fastest working version. It usually mentions that you should move it later. Later has a way of not arriving. The key then gets committed, and git history keeps it forever, including after you delete the line.

The check: search your repo and its history for anything shaped like a credential. The fix has a strict order, rotate at the provider first, clean up second. If a key of yours is public right now, stop reading this and follow the leaked key runbook instead; it is this paragraph expanded into ordered steps. Otherwise, this prompt does the sweep. It is written for Cursor's agent mode, so let it work through the repo and read the rotation list it gives you at the end.

Paste this into your AI coding tool
Act as a security reviewer for this repository. Search every file, including config files and anything in git history, for hardcoded secrets: API keys, database passwords, tokens, connection strings.

For each one you find:
1. Tell me the file, the kind of secret, and whether it also appears in past commits.
2. Move it into an environment variable loaded from .env, and add .env to .gitignore if it is not there.
3. Add the variable name to .env.example with a placeholder value.

Finish with a rotation list: every secret that ever appeared in a commit, so I can rotate each one at its provider. Rotation matters because git history keeps old file versions even after the code is cleaned up.

2. Routes that trust the browser

Ask Cursor for an admin dashboard and you will usually get a working one: the page renders, non-admins get redirected, everything looks correct. Now call the API route behind it directly. The pattern we see most in AI-generated Next.js and Express code is that the protection lives in the frontend, a hidden button, a client-side redirect, while the route itself answers anyone who asks. Same for record ownership: if changing the ID in /api/orders/1041 returns someone else's order, the route never asked who was calling.

The mechanical way to check: open your routes folder, whatever your framework calls it, and read the list of files as an attacker would, one endpoint at a time. For each, two questions. Who does the server think is calling, and where exactly in the code does it check? "The page redirects you" is not an answer; the page is not the route. This is the check most worth doing carefully, because it fails silently. Your app works, your tests pass, and the route is open. Paste this into Cursor and make it show its work:

Paste this into your AI coding tool
Audit every API route, server action, and server function in this app that reads or writes user data. Build me a table with one row per route:

1. Does it verify on the server that the request comes from a logged-in user? Client-side redirects and hidden UI do not count.
2. Does it check that the caller is allowed to touch the specific record requested, so changing an ID in the request cannot reach another user's data?
3. If it is an admin-only route, where exactly is the admin check, and is it server-side?

Then fix every route that fails a check by adding the missing server-side verification. Keep the changes minimal and do not alter routes that already pass.

3. Input handled for the happy path only

Cursor writes the version of a form handler that works when the user types what you expect. Whether it also handles the user who types query fragments into the search box (SQL injection) or a script tag into their display name (cross-site scripting) is inconsistent, because you never asked, and the demo never breaks. The principle to check for: user input is data, never instructions. Queries should be parameterized, and user content should be escaped before it renders. Ask Cursor to trace every path from an input to a query or a page and fix the ones that pass content through raw.

A note on trust here: the model that wrote the flaw will cheerfully audit its own work and miss the same thing twice. Asking is still worth it, Cursor with an explicit security instruction catches real issues it skipped when nobody asked. Just treat "I found no problems" as one input, not a verdict.

4. Dependencies frozen at generation time

Every package Cursor picked was current the day it wrote the import, and has been aging since. Some of them now have publicly documented vulnerabilities with fixes already published. This is the least dramatic item on the list and the easiest to clear: your package manager's audit command compares your lock file against the public databases, and GitHub's dependency alerts can do it continuously if enabled on the repo. Run it, read the results, update what is actually reachable from your code. One habit keeps this cheap: audit the lock file, not just the packages you asked for, because most of what your app depends on arrived as a dependency of a dependency, chosen by nobody.

5. Scaffolding that never came down

Debug logging, verbose error pages, a /api/test route from week one, a seeded admin account with a password you both agreed was temporary. Cursor builds fast partly by building scaffolding, and nothing in the workflow reminds you to strike it. Trigger an error in production on purpose: if the response includes stack traces or query text, detailed errors are still on. Then skim your routes file for anything you would not want a stranger to find, because strangers are good at finding routes.

What checking by hand can't tell you

The five checks above are real work in a full-sized app, and even done well they share a limit with any scan: they read code. Whether your discount logic can be gamed, whether a key was copied before you rotated it, whether someone talks a user out of their password, none of that is in the repo. The full vibe coding checklist covers those honestly. The job here is narrower: make sure the checkable things get checked, in an app whose code you may never have fully read.

Frequently asked questions

Is Cursor safe to use?

As an editor, yes, in the same sense any development tool is: Cursor publishes its own security documentation covering how it handles your source code, and that is a reasonable thing to read if you work on sensitive codebases. But that question is about Cursor the product. The question this article answers is whether the app Cursor wrote for you is ready for real users, and that depends entirely on the code, not the editor.

Is code written by Cursor secure?

Sometimes, and not reliably. Research from Veracode found that AI-generated code introduced security flaws in roughly 45 percent of tests, across models and tools. Cursor is not worse than its peers here; the point is that no AI coding tool consistently writes secure code without being asked, so checking is your job either way.

Does this apply to Copilot or Windsurf too?

Yes, all of it. The checks in this article are about what AI-generated code tends to get wrong, not about Cursor specifically. If you build with Copilot, Windsurf, or any other AI-assisted editor, the same five checks apply, and the fix prompts work with minor rewording.

How is this different from Cursor's own security page?

Cursor's security page describes how Cursor protects your source code: certifications, infrastructure, privacy mode. It is about their handling of your data. This article is about your handling of your users' data, in the app Cursor helped you build. Both matter; they are just different questions.

Cursor did its part: you have an app. The five checks above are yours, and none of them needs more than an afternoon. Run them, or let a scan run the checkable ones for you, and make sure it's actually done.

Ship it with confidence.

Your first scan takes about two minutes. Your first fix might too.

  • No credit card
  • Read-only access
  • Cancel anytime