Cursor
Cursor app pre-launch security checklist
A practical checklist for apps built with Cursor before you share the link. Secrets, auth, Supabase or Firebase rules, headers, files and dependencies.
Updated 2026-10-27
Cursor writes code fast and follows the patterns already in your repo, good and bad. It does not know which values are secret, which routes must check a login, or which database tables are public. That is your job before launch. Work through this list on the deployed app, not just in the editor, because many problems only appear in the build.
1. Search for secrets in your source
git grep -nE "sk_live_|sk-[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|service_role|sb_secret_|eyJ[A-Za-z0-9_-]{20,}"
Move every hit into an environment variable that only server code reads.
2. Check public env prefixes
Anything with NEXT_PUBLIC_, VITE_, PUBLIC_ or EXPO_PUBLIC_ is shipped to every visitor. Only the Supabase URL, the anon or publishable key, and similar public values belong there. A secret in a public variable is published.
3. Search the built bundle
npm run build
grep -rEl "service_role|sb_secret_|sk_live_" .next dist build 2>/dev/null
No output is what you want. Remember that a key can be in the build but not in your visible source.
4. Keep env files out of Git and out of Cursor's context
Add .env* to .gitignore. Add the same patterns to .cursorignore so the editor does not index them. If a key was ever committed, rotating it matters more than deleting the file, because Git history keeps it. Check with git log --all -p -S"service_role".
5. Make the server check who is calling
Generated API routes often trust whatever the browser sends. Every route that reads or changes private data needs two checks: is there a valid session, and does this user own this record. Do not rely on hiding a button in the UI, and do not rely on middleware alone.
// app/api/invoices/[id]/route.ts
const user = await getUserFromSession(request);
if (!user) return new Response("Unauthorized", { status: 401 });
const invoice = await db.invoice.findUnique({ where: { id: params.id } });
if (!invoice || invoice.ownerId !== user.id) return new Response("Not found", { status: 404 });
6. Turn on database rules
If you use Supabase, enable row level security on every table in the public schema and write real policies. See the Supabase RLS guide. If you use Firebase, replace test-mode rules; see Firebase rules. Test with two accounts: user A must not see user B's rows.
7. Add security headers
Set HSTS, a Content-Security-Policy, frame protection, nosniff and a referrer policy. Copy-paste config is in Security headers for AI-built apps.
8. Make sure nothing private is being served
Request these paths on your live domain and expect 404:
curl -s -o /dev/null -w "%{http_code} /.env\n" https://your-app.example/.env
curl -s -o /dev/null -w "%{http_code} /.git/HEAD\n" https://your-app.example/.git/HEAD
curl -s -o /dev/null -w "%{http_code} /package.json\n" https://your-app.example/package.json
Also consider turning off production source maps, or uploading them only to your error tracker.
9. Check your dependencies
AI tools sometimes suggest packages that do not exist or have names close to real ones. Before you install, check that the package is the well-known one: downloads, repository, maintainer. Run npm audit, and read lockfile changes in pull requests, not only your own code.
10. Limit abuse on expensive routes
Add rate limits to login, signup, password reset and any route that calls a paid API such as an LLM. Without limits, one script can run up your bill or lock out your users.
11. Run an outside scan, then re-run after fixes
Paste your deployed URL into the free Vibe Scan. It reads the public page, scripts and headers the way a browser would, and returns a grade from A to F with the single worst finding. Fix that finding, redeploy, and scan again.
Give Cursor a rules file
Put this in .cursor/rules so later prompts do not undo your fixes:
- Never put secrets in client code or in NEXT_PUBLIC_, VITE_ or PUBLIC_ variables.
- Never use the Supabase service role or secret key in the browser.
- Every API route must verify the session and the record owner.
- New Supabase tables must have row level security and explicit policies.
- Do not add dependencies without telling me the package name and why.
Show your grade
If you land on an A or B, embed the badge from your scan result page in your README or footer. It links back to the result, which tells visitors you checked.
FAQ
Does Cursor make code less secure than writing it by hand?
Not by itself. It repeats patterns quickly, including unsafe ones, and it lacks context about what is secret. Review its output the way you would review a new teammate's.
Do I need this checklist if I use Supabase Auth?
Yes. Auth identifies users. You still need row level security, server-side ownership checks and key hygiene.
How often should I re-check?
Before launch, after any change to auth, payments or database schema, and after adding a new third-party script.
Can an outside scan see everything?
No. A passive scan sees what the public can see. It cannot read your private code or test logged-in flows, so keep checks 5 and 6 on your own list.