fixes / launch-ready

How I Would Fix exposed API keys and missing auth in a Cursor-built Next.js internal admin app Using Launch Ready.

The symptom is usually ugly but simple: someone opens the app, views source or network requests, and finds live API keys sitting in the browser bundle,...

How I Would Fix exposed API keys and missing auth in a Cursor-built Next.js internal admin app Using Launch Ready

The symptom is usually ugly but simple: someone opens the app, views source or network requests, and finds live API keys sitting in the browser bundle, while the admin screens are accessible with no real login gate. In business terms, that means exposed customer data, accidental writes, support load, and a real chance of abuse before you even notice.

The most likely root cause is that the app was built fast in Cursor with secrets placed in client-side code and pages protected only by "hidden links" or weak UI checks. The first thing I would inspect is the deployment output and the auth flow together: which env vars are public, which routes are server-only, and whether any admin actions can be called directly from the browser without session validation.

Triage in the First Hour

1. Check the production site in an incognito window.

  • Confirm whether admin pages load without login.
  • Try direct URLs for `/admin`, `/dashboard`, `/api/*`, and any internal routes.

2. Inspect browser DevTools.

  • View page source and bundled JS for leaked keys.
  • Check Network tab for API calls made from the client.
  • Look for tokens in request headers, query strings, or localStorage.

3. Review deployment environment variables.

  • Compare `.env.local`, Vercel/Netlify/Cloudflare settings, and production secrets.
  • Identify anything using `NEXT_PUBLIC_` that should not be public.

4. Audit authentication files.

  • Check middleware, route handlers, server actions, and any custom guards.
  • Confirm whether auth is enforced on the server, not just in React state.

5. Review logs and monitoring.

  • Look for unusual spikes in API usage, failed logins, or anonymous admin traffic.
  • Check if any secret was used from unexpected IPs or countries.

6. Verify connected accounts.

  • Rotate any exposed API keys immediately if they can write data or bill usage.
  • Check Stripe, OpenAI, email provider, database access tokens, and webhook secrets.

7. Inspect recent commits and Cursor-generated changes.

  • Find where auth checks were skipped or where env vars were moved into client code.
  • Review build output for warnings about client/server boundary mistakes.

8. Freeze risky operations if needed.

  • Temporarily disable destructive admin actions.
  • Add a maintenance banner if there is active abuse risk.

A useful first diagnostic command is checking for public env usage:

grep -R "NEXT_PUBLIC_" . && grep -R "localStorage" app components lib

If I find secrets in client code or missing server-side auth on admin routes, I treat it as a production incident first and a code issue second.

Root Causes

1. Secrets were placed in client-exposed variables.

  • Confirm by searching for `NEXT_PUBLIC_` on anything that looks like an API key, service token, or private endpoint secret.
  • Also inspect build artifacts and bundled JS to see if the value appears in compiled output.

2. Admin access was protected only by UI logic.

  • Confirm by opening protected URLs directly without logging in.
  • If the page renders data before any server check runs, the protection is fake.

3. API routes trust the browser too much.

  • Confirm by calling route handlers from an unauthenticated session and checking whether they still return data or accept writes.
  • If POST endpoints do not verify session or role on the server, they are open by default.

4. Cursor generated helper code that bypassed security patterns.

  • Confirm by comparing new files against your existing auth conventions.
  • Common smell: duplicated fetch wrappers, ad hoc token checks, or copied examples that never got hardened.

5. Environment separation is broken.

  • Confirm if staging keys work in production or vice versa.
  • If one shared key powers multiple environments, a leak becomes a full outage risk.

6. There is no role-based access control at all.

  • Confirm by checking whether every logged-in user gets full admin access regardless of role.
  • Internal apps still need least privilege because "internal" does not mean safe.

The Fix Plan

My priority would be to stop exposure first, then rebuild access control around the server boundary. I would not try to patch this with one more client-side check because that just delays the next incident.

1. Rotate every exposed secret immediately.

  • Revoke leaked API keys and issue new ones.
  • Update all downstream systems that depend on them: billing webhooks, email providers, AI APIs, storage services, analytics tools.

2. Move all private secrets out of client code.

  • Anything sensitive must live only on the server side: route handlers, server actions, backend services, or edge functions with proper controls.
  • Public values should be treated as public forever.

3. Add real authentication at the app boundary.

  • Use a proven auth provider or Next.js-compatible session system with secure cookies.
  • Protect all admin routes on the server with middleware plus route-level checks where needed.

4. Add authorization checks for each action.

  • Do not assume login equals permission to do everything.
  • Enforce roles like `admin`, `editor`, and `viewer` before reads and writes.

5. Lock down API routes with least privilege.

  • Require authenticated sessions for internal endpoints.
  • Validate inputs strictly so bad payloads do not reach your database or third-party APIs.

6. Move sensitive operations behind server-only functions.

  • Browser code should request an action; it should not hold credentials needed to perform it directly.
  • This reduces leak radius if someone inspects frontend code again later.

7. Add secure defaults around deployment config.

  • Set `HttpOnly`, `Secure`, and `SameSite` on cookies where applicable.
  • Restrict CORS to known origins only if cross-origin access is actually required.

8. Add logging without leaking secrets into logs.

  • Log user ID, route name, status code, and action type.
  • Never log full tokens, raw Authorization headers, or private request bodies.

9. Create a hard fail for missing auth in production.

  • If auth middleware fails to load or config is missing, deny access rather than allow it.
  • Silent fallback-to-open is how internal tools become public tools.

10. Clean up old builds and invalidate caches if needed: ```bash rm -rf .next npm run build ``` Then redeploy only after confirming no secret appears in bundle output or network responses.

Here is the decision path I would use:

For a Cursor-built Next.js app specifically, I would also review every place where data fetching happens:

  • Server components should fetch protected data only after auth verification.
  • Client components should never receive private credentials through props unless it is truly non-sensitive public config.
  • Route handlers should reject anonymous requests even if the UI already hides buttons.

Regression Tests Before Redeploy

I would not ship this fix until I have proof that both exposure paths are closed: secret leakage and unauthorized access. The test plan should be small but ruthless.

Acceptance criteria:

  • No private key appears in page source, JS bundles, logs, or browser storage.
  • Anonymous users cannot load admin pages or call admin APIs successfully.
  • Non-admin users cannot perform admin actions even when authenticated.
  • Protected endpoints return 401 or 403 consistently when expected.
  • Build succeeds with no security-related warnings ignored.

QA checks: 1. Open every internal route in incognito mode. 2. Refresh protected pages directly from URL bar instead of navigating through links only once logged in already normal user flow works? 3. Attempt read-only API calls without session cookies returned denial? 4. Attempt write actions as a lower-role account denied? 5. Verify logout invalidates access immediately enough for your risk profile? 6. Check that secrets do not appear in: -.next build artifacts browser DevTools response payloads error messages 7. Test mobile layout too because broken auth screens often fail there first due to hidden navigation states? 8. Confirm empty states and loading states do not expose internal data while waiting?

I would also add one regression gate in CI:

  • Fail build if any file under `app/`, `components/`, or `lib/` contains known secret patterns or uses dangerous public env naming for private values?

If you have automated tests already:

  • Target at least 80 percent coverage on auth-critical flows?
  • Include one test per protected route plus one test per privileged mutation?
  • Run these tests before every deploy?

Prevention

The best prevention is making insecure shortcuts harder than secure ones.

1. Code review guardrails

  • Every admin route needs explicit server-side auth review before merge?
  • Any new env var must be classified as public or private?
  • Any direct third-party API call from client code gets blocked unless there is a clear reason?

2. Security guardrails

  • Rotate secrets on a schedule and immediately after any leak?
  • Store private values only in approved secret managers or platform env settings?
  • Enforce rate limits on login and sensitive endpoints to reduce abuse?

3. UX guardrails

  • Show clear login states so users know why content is unavailable?
  • Use distinct empty/error states instead of silently rendering partial admin UI?
  • Avoid hiding security behind CSS because that creates false confidence?

4. Monitoring guardrails

  • Alert on spikes in anonymous requests to `/api/admin/*`?
  • Alert on repeated failed authorization attempts from same IP/user agent?
  • Track unusual outbound API usage so leaked keys do not burn budget unnoticed?

5. Performance guardrails

  • Keep auth checks fast so nobody removes them "for speed" later?
  • Cache safe public assets separately from protected responses?
  • Watch p95 latency on login and protected dashboard loads; I would want p95 under 300 ms for normal internal traffic?

6. Process guardrails

  • Maintain a short handover checklist for every deploy: secrets rotated? auth verified? rollback ready? monitoring live?
  • Require one human review pass after Cursor-generated changes touching auth or env handling?
  • Keep prod/staging accounts separate so mistakes do less damage?

When to Use Launch Ready

Use Launch Ready when you need me to fix this fast without turning it into a long consulting project.

This sprint fits best when:

  • You have a working Cursor-built Next.js app but it is not production-safe yet?
  • You need exposed secrets removed before more people see them?
  • You want proper auth added without breaking the current product flow?
  • You need one senior engineer to make launch decisions instead of guessing?

What I need from you before starting:

  • Access to your repo
  • Access to hosting platform like Vercel or similar
  • Access to DNS provider
  • Access to Cloudflare if already used
  • A list of third-party services connected to the app
  • Any existing login rules or roles you want preserved

What you get back:

  • A fixed production deployment path within 48 hours
  • Secrets moved out of harm's way
  • Auth repaired around actual server checks
  • A handover note explaining what changed and what still needs follow-up

If your app has already leaked something sensitive publicly once, I would treat speed as part of security here because every extra day increases risk of misuse and support damage.

References

1. Roadmap.sh API Security Best Practices: https://roadmap.sh/api-security-best-practices 2. Roadmap.sh Code Review Best Practices: https://roadmap.sh/code-review-best-practices 3. Next.js Security Headers: https://nextjs.org/docs/app/building-your-application/configuring/security 4. OWASP Authentication Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html 5. OWASP Session Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html

---

Take the next step

If this is a problem in your product right now, here is what to do next:

  • [Use the free Cyprian tools](/tools) - estimate cost, score app risk, check launch readiness, or pick the right service sprint.
  • [Book a discovery call](/contact) - I will tell you honestly whether you need a sprint or if you can DIY the next step.

*Written by Cyprian Tinashe Aarons - senior full-stack and AI engineer helping founders rescue, launch, automate, and scale AI-built products.*

Next steps
About the author

Cyprian Tinashe AaronsSenior Full Stack & AI Engineer

Cyprian helps founders rescue, secure, deploy, and automate AI-built apps with production-grade engineering, launch systems, and AI integration.