Move API keys off the client bundle — Cursor
Keys in the JavaScript bundle are public. Attackers scan GitHub and deployed bundles for them 24/7. One exposed Stripe secret or OpenAI key can drain your account in hours.
Fixing this in Cursor
Agentic AI code editor built on VSCode
Next.js: `NEXT_PUBLIC_*` is client, anything else is server-only. Read secrets via `process.env.*` from a Server Component, Server Action, or `app/api/*/route.ts`.
Files to touch in Cursor:
.env.localapp/api/**/route.tsUsing a different tool? Pick your stack:
The prompt for Cursor
Copy and paste this into your Cursor chat exactly as-is.
Apply these changes to my codebase. Edit the files directly and keep existing formatting: CRITICAL: Move exposed API keys server-side immediately 1. CRITICAL: API keys are exposed in the frontend. Move all keys to environment variables immediately. 2. Create a server-side API route (app/api/) for each external API call that needs a secret key. 3. Remove any hardcoded secrets from client-side code — only use process.env.* in server components and API routes. 4. Never prefix secret keys with NEXT_PUBLIC_ — that exposes them to the browser. 5. Add .env* to .gitignore immediately. 6. Rotate every leaked key in the provider dashboard — assume they are compromised.
Why this matters
Every AI coding tool, when asked to integrate Stripe, OpenAI, or Supabase, has at some point written the secret key directly in a React component. The component ships to the browser, the browser downloads the JS bundle, the secret is now public forever — even after you "fix" it, attackers who scraped the bundle still have it.
Automated bots crawl GitHub, npm, Vercel deployments, and Lovable shares looking for exposed keys. The time from "key pushed" to "key abused" is often under 30 seconds. OpenAI has a team that watches for this and rotates keys automatically — but only if their detection catches it before an attacker does.
This is the #1 security finding in our audits of Lovable and Bolt apps. The fix is always the same: move the key to a server environment variable, create a backend endpoint that the client calls, and let the backend use the secret to talk to the real API.
How to use this prompt in Cursor
- 1. Open your Cursor project.
- 2. Copy the prompt above with the copy button.
- 3. Paste into the Cursor chat and send.
- 4. Review the diff, accept the changes, redeploy.
- 5. Verify the fix using the checklist below.
Common mistakes to avoid
- error_outlineUsing `NEXT_PUBLIC_STRIPE_SECRET_KEY` — the prefix made it public. Every `NEXT_PUBLIC_*` ships to the browser.
- error_outlineCalling OpenAI directly from a React component — the key is downloaded with the JS bundle.
- error_outlineCommitting `.env` to git instead of `.env.local` — `.env` is often tracked by default.
- error_outlineUsing the Supabase `service_role` key in a client — it bypasses RLS and reads/writes everything.
- error_outlineShipping a key in an API route but logging `process.env` on error, leaking into logs.
How to verify the fix worked
- check_circleOpen DevTools → Sources → search for the key value — must return 0 matches.
- check_circle`curl https://yoursite.com/ | grep "sk_live"` — returns nothing for Stripe secret keys.
- check_circleRotate the key after exposure — old keys are compromised forever even if "pulled".
- check_circleSet up GitGuardian or git-secrets on the repo to catch future leaks pre-commit.
Frequently asked questions
What is the difference between anon and service-role Supabase keys?expand_more
How do I tell if my key leaked?expand_more
Is the GitHub history a problem if I deleted the key?expand_more
Want all 34 prompts tailored to your Cursor site?
Pantra scans your site in 10 seconds, detects the stack, and generates the exact prompts that apply — only the ones you actually need.
Scan my siteRelated Cursor prompts
Enable Supabase Row Level Security on every table — Cursor
Prompt to enable RLS on every Supabase table and write sane policies — the #1 security fix for Lovable, Cursor, Bolt, v0, Replit, Windsurf, Claude Code, Base44 apps.
SecurityAdd security headers (CSP, HSTS, X-Frame, etc.) — Cursor
Stack-specific prompt to ship Content-Security-Policy, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy in Lovable, Cursor, Bolt, v0, Replit, Windsurf, Claude Code, Base44.
SecurityForce HTTPS and enable HSTS — Cursor
Prompt to redirect all HTTP to HTTPS and enable HSTS — non-negotiable for modern sites. Works in any stack.