Is my Cursor app secure?
Cursor is the editor on your machine. It does not host the app, and it does not pick a backend. The leaks show up in whatever you asked it to build, usually after a prompt like "just make the query work."
Free check
Check the live app
Paste the public Cursor URL. The check reads what a visitor's browser can already see, then gives you a private report with a fix prompt for each issue.
What Cursor actually ships
Cursor can write any stack you point it at. A lot of shipped apps are Next.js deployed on Vercel, or a Vite app, often with Supabase or Firebase added in the same chat. Those are common choices, not a rule. The checks below follow the code that actually got deployed: client bundles, env prefixes, database rules, and files the host serves.
Mistakes worth checking
These are the ones that show up in apps built with Cursor. Each step is something you can do in the browser or in the product dashboard.
Critical
NEXT_PUBLIC_ or VITE_ on a real secret
Next.js inlines every NEXT_PUBLIC_ variable into the client bundle. Vite inlines every VITE_ variable. Cursor will keep the prefix you, or a sample, already used. A service role key, a Stripe secret, or an OpenAI key with either prefix is public on deploy.
Check it yourself
Search the repo for NEXT_PUBLIC_ and VITE_. Then search the live JavaScript for service_role, sk-, sk_live, and rk_. A name that is only in a server file, with no public prefix, is the pattern you want.
High
Row-level security turned off to clear an error
The first Supabase error in a Cursor chat is often a permission error. A fast fix is to disable row-level security or to add a policy of true. The feature starts working. The table is then readable with the anon key.
Check it yourself
In the Supabase dashboard, every table in the public schema should have row-level security on. Open each policy. Private data should require auth.uid() to match the row's user. Deploy again only after that is true.
Critical
A committed .env that the host serves
Local tools read .env so you can develop. If that file is committed, or copied into a public folder, some hosts will serve it at /.env. Values belong in the host's environment settings.
Check it yourself
Open https://your-domain/.env, /.env.local, and /.env.production. A download is a leak. Remove the file from the deploy and rotate every value that was in it.
High
Firebase left in test mode
Firebase test rules are open so you can prototype. They allow reads and writes without a login. Agents scaffold them and then ship the app. The public web API key in the page is expected. The rules are the lock.
Check it yourself
In the Firebase console, Realtime Database rules should not set ".read" or ".write" to true. Firestore rules should require request.auth, then a tighter match on the user id. Publish the rules and try the data URL while signed out.
Medium
Production source maps left on
Next.js stays quiet about browser source maps unless productionBrowserSourceMaps is enabled. Vite publishes them when build.sourcemap is on. Either setting can hand a visitor your original files.
Check it yourself
View a production script from your domain and search for sourceMappingURL. Open the map. If it contains sourcesContent or your original paths, turn the setting off and delete the .map files.
A prompt you can paste
Paste this into Cursor, publish again, and run the check a second time. If a key was already on the live site, rotate it in the vendor dashboard. The prompt cannot do that part.
Audit this project for secrets and open data that a visitor can already see. Change the code, and do not disable a safeguard to make a page load. 1. Remove from client components, and from any NEXT_PUBLIC_ or VITE_ variable: Supabase service_role keys, Stripe secret or restricted keys (sk_ and rk_), OpenAI and Anthropic keys, AWS and GitHub tokens, private keys, and database URLs with passwords. The Supabase anon key and a Stripe publishable key (pk_) may stay in the browser. 2. Put provider calls and service-role work in server-only code. On Next.js, use a Server Action or a route handler that reads a normal environment variable. On Vite, use a server function, not a VITE_ variable. 3. Enable Supabase row-level security on every public table and replace any policy of true. For Firebase, remove test-mode rules and require auth for reads and writes. 4. Stop the host from serving .env, .git, and source maps. In Next.js leave productionBrowserSourceMaps off. In Vite set build.sourcemap to false for production. 5. List the key names that were exposed so I can rotate them. Do not print secret values. After the edits, tell me the files you changed.
What the check looks at
- The public page and the JavaScript it loads, for common leaked secret keys: a Supabase service role key, OpenAI, Anthropic, Stripe secret keys, AWS, GitHub, Slack, private keys, and database URLs that include a password. A Supabase anon key is called out as expected in the browser.
- A short list of public paths: /.env, /.env.local, /.env.production, /.git/config, /.git/HEAD, and /.npmrc.
- A source map, only when a script on the page already points at one, and only when that map includes original source.
- Supabase tables, only when the page already includes a supabase.co address and the public anon key. It asks for one row per table, then drops that row.
- Firebase Realtime Database and Firestore, only when the public config is already in the page. It uses that public config and does not sign in.
- A few browser safety headers on the main response. Missing headers are noted when two or more of the watched ones are absent. They are less urgent than a leaked key.
What stays outside it
- It reads. It does not log in, submit forms, or change data.
- It does not guess passwords, fuzz inputs, or hunt through hidden paths.
- It does not use any secret it finds, including a service role key.
- It does not open your builder's dashboard. A rule that lives only there can stay invisible.
- A clear result describes this public look. It is not a certificate that the whole app is safe.
- Cursor is the editor. The check looks at the URL you deployed, not at the chat transcript or the files that never got published.
Questions
Free check
Run it on the published URL
Use the address a customer would type. The report stays private, and the shareable scorecard hides the details.
Other builders
- Is my Lovable app secure?Service role keys, row-level security, and variables that ship to the browser.
- Is my Bolt app secure?Vite variables, Supabase locks, and Bolt Database access you confirm by hand.
- Is my Replit app secure?Secrets in the page, a public Repl, and DATABASE_URL where a visitor can read it.
- Is my v0 app secure?Next.js client bundles, Vercel env vars, and optional Supabase or Neon.
- Is my Base44 app secure?Entity rules you check by hand, plus Vite secrets and service-role calls.
- Is my Windsurf app secure?Agent edits that ship a secret, loosen a database rule, or publish a source map.
- Is my Bubble app secure?Privacy rules, API Connector secrets, and the Data API admin token.