How I Would Fix exposed API keys and missing auth in a Cursor-built Next.js marketplace MVP Using Launch Ready.
The symptom is usually obvious: a founder ships a Next.js marketplace MVP, then notices API keys in the browser bundle, public GitHub repo, or network...
How I Would Fix exposed API keys and missing auth in a Cursor-built Next.js marketplace MVP Using Launch Ready
The symptom is usually obvious: a founder ships a Next.js marketplace MVP, then notices API keys in the browser bundle, public GitHub repo, or network tab, while sensitive actions like creating listings, editing profiles, or viewing orders work with no real auth gate. In business terms, that means anyone can impersonate users, scrape data, burn API credits, trigger support issues, and create a launch blocker the moment traffic arrives.
The most likely root cause is that Cursor generated a fast prototype with client-side shortcuts: secrets placed in `NEXT_PUBLIC_*` variables, server actions or API routes without authorization checks, and pages that trust the frontend instead of verifying identity on the server. The first thing I would inspect is the deployment surface: the live app bundle, environment variables in Vercel or Cloudflare, and the exact endpoints that change data.
Triage in the First Hour
1. Check whether any secret is exposed in the browser.
- Open DevTools Network and Sources.
- Search loaded JS bundles for key names like `sk_`, `pk_`, `supabase`, `firebase`, `stripe`, `openai`, or vendor-specific tokens.
- Confirm whether any secret appears in page source or static assets.
2. Inspect the deployment environment.
- Review Vercel, Cloudflare Pages, or your host's env var list.
- Look for secrets stored as public variables such as `NEXT_PUBLIC_API_KEY`.
- Confirm production and preview environments are separated.
3. Audit the sensitive routes.
- List every endpoint that creates, updates, deletes, or returns private data.
- Check whether each route validates session identity on the server.
- Verify whether middleware protects admin pages and marketplace management screens.
4. Review auth implementation.
- Identify whether auth is custom JWT, Clerk, Auth.js/NextAuth, Supabase Auth, or something else.
- Confirm session cookies are httpOnly and secure.
- Check if role checks exist for buyer, seller, and admin actions.
5. Inspect recent builds and commits.
- Find when secrets were introduced.
- Check if a recent Cursor-generated refactor moved server code into client components.
- Review any "temporary" bypasses like `if (true)` guards or mock auth left behind.
6. Check logs and monitoring.
- Look for unusual traffic to write endpoints.
- Review failed auth attempts and 401/403 rates.
- Inspect uptime alerts for error spikes after deploys.
7. Freeze risky changes.
- Pause marketing spend if users can hit broken flows or exposed data paths.
- Disable non-essential write endpoints until authorization is confirmed.
A simple way to think about it:
Root Causes
1. Secrets were put into client-side env vars.
- Confirmation: search `.env`, Vercel env settings, and code for `NEXT_PUBLIC_` prefixes on anything sensitive.
- If a secret is accessible in browser JS or build output, it is already compromised.
2. API calls are made directly from React components with no server proxy.
- Confirmation: look for fetch calls from client components hitting third-party APIs directly with secret-bearing headers or query params.
- If the browser can call it with a secret, users can copy it too.
3. Protected routes rely only on frontend hiding.
- Confirmation: log out and try hitting `/dashboard`, `/admin`, `/seller/listings/edit/[id]`, or equivalent URLs directly.
- If the page loads but just hides buttons client-side, there is no real protection.
4. Server routes trust user-provided IDs without ownership checks.
- Confirmation: inspect API handlers for `userId`, `sellerId`, or `listingId` taken from request body without comparing against session user ID.
- This creates IDOR risk: one user can act on another user's records.
5. Middleware exists but does not cover all paths.
- Confirmation: review `middleware.ts` matcher patterns and compare them to actual protected routes and API endpoints.
- It is common to protect pages but forget `/api/*` write routes.
6. Cursor-generated code mixed demo logic with production logic.
- Confirmation: search for mock data branches, hardcoded admin emails, temporary bypass flags, or copied sample code from docs that never got removed.
- This usually shows up as "works locally" but fails under real auth rules.
The Fix Plan
My priority is to stop exposure first, then repair access control without breaking the marketplace flow. I would not try to redesign everything at once; I would make small safe changes so we can ship in 48 hours without creating new outages.
1. Rotate every exposed secret immediately.
- Revoke the leaked keys at the provider level first.
- Issue new keys and store them only in server-side environment variables.
- Assume anything seen in a bundle or repo has been copied already.
2. Remove secrets from client code paths.
- Replace any direct browser-to-vendor calls with server-side API routes or server actions.
- Keep vendor credentials inside route handlers only.
- Use short-lived tokens where possible instead of long-lived master keys.
3. Add server-side authentication checks to every sensitive route.
- Require a valid session before reading private data or mutating records.
- Enforce role checks for seller/admin operations separately from buyer operations.
- Reject requests early with 401 for unauthenticated users and 403 for unauthorized users.
4. Add ownership validation on every record mutation.
- Compare session user ID to record owner ID before update/delete/read of private resources.
- Never trust IDs sent from the browser alone.
- Use database queries that include both record ID and owner ID in the filter.
5. Lock down middleware and route protection patterns.
- Protect all dashboard-like pages plus all `/api/*` write endpoints that touch private data.
- Keep public pages public on purpose: home page, marketplace browse pages if intended, legal pages, pricing pages.
- Do not overblock public SEO pages unless they truly need login.
6. Clean up environment separation across preview and production.
- Put test keys in preview only if they are safe sandbox credentials."
- Ensure prod deploys cannot accidentally use dev databases or dummy auth settings."
- Verify redirects so login callbacks land on the correct domain."
7. Add basic logging around denied access attempts."
- Log route name, user ID if present, request ID, and denial reason."
- Do not log full secrets or PII."
- This helps distinguish abuse from normal user errors."
8. Patch deployment hygiene."
- Remove leaked secrets from git history if needed."
- Update `.gitignore` and env documentation."
- Confirm build artifacts are not publishing private values."
One practical diagnostic check I would run right away:
grep -R "NEXT_PUBLIC\|sk_\|pk_\|secret\|token" app components lib pages src .env* --exclude-dir=node_modules
That will not solve anything by itself, but it quickly tells me whether secrets are sitting in places they should never be.
Regression Tests Before Redeploy
I would not redeploy until these checks pass:
1. Auth gate tests
- Unauthenticated users get redirected or blocked from protected pages within one request cycle.
- Unauthenticated requests to protected APIs return 401 consistently.
2. Authorization tests
- A buyer cannot edit a seller listing they do not own.
- An authenticated seller cannot access another seller's dashboard data by changing an ID in the URL or request body.
3. Secret exposure tests
- No sensitive key appears in browser source maps, JS bundles, HTML output, logs, or public repo files.
- Build artifacts do not contain production secrets when searched with grep-like scans.
4. Role-based flow tests
- Buyer signup/login works end to end.
Seller signup/login works end to end." Admin-only actions remain blocked for non-admin accounts."
5. Negative path tests Invalid sessions fail cleanly." Expired cookies force re-authentication." Tampered IDs return denial rather than data leakage."
6. Smoke test after deploy Browse marketplace listing pages." Create account." Login/logout." Create one safe test listing." Edit profile." Confirm no console errors on critical screens."
Acceptance criteria I would use:
- Zero exposed production secrets in client-visible output."
- Zero unauthenticated writes to private endpoints."
- Zero cross-account reads/writes across buyer/seller/admin roles."
- p95 response time stays under 300 ms for protected page loads after adding auth middleware."
- No increase in checkout or onboarding abandonment caused by broken redirects."
Prevention
If I were hardening this after launch," I would add guardrails at four levels."
1. Code review guardrails Every PR touching auth must show who can read/write which resource." Reject any direct use of secret-bearing APIs from client components." Require at least one reviewer to check route protection and ownership logic."
2. Security guardrails Use httpOnly secure cookies for sessions." Separate read-only public APIs from authenticated write APIs." Add rate limits on login," password reset," invite," and write endpoints." Set strict CORS so only approved origins can call your APIs." Rotate keys quarterly even if nothing leaks."
3. QA guardrails Keep an auth regression checklist for every release." Test logged-out," logged-in," expired-session," wrong-role," and wrong-owner cases." Add one automated test per critical endpoint before shipping."
4. UX guardrails Show clear loading," empty," error," and permission states instead of blank screens." If access is denied," explain what happened and what to do next." Bad permission UX often leads founders to weaken security later just to reduce support tickets."
If you want fewer incidents later," make security visible in your release process rather than hidden inside engineering notes."
When to Use Launch Ready
Launch Ready fits when you have a working Cursor-built MVP but need it made production-safe fast: domain setup," email deliverability," Cloudflare," SSL," deployment," secrets handling," monitoring," redirects," subdomains," caching," DDoS protection," SPF/DKIM/DMARC," plus a clean handover checklist."
I use this sprint when the product is close enough to launch that fixing infrastructure will unlock revenue faster than rebuilding features." For this kind of rescue work,"
burn ad spend," or ship an app that leaks data on day one."
What you should prepare before booking:
- Access to hosting,"
Cloudflare," domain registrar," and email provider accounts."
- Repo access with deploy permissions."
- A list of all sensitive flows:"
signup," login," checkout," dashboard," admin," and any AI/tooling endpoints."
- Any known leaked keys so I can rotate them immediately."
If your app already has traffic," I would treat this as urgent rather than cosmetic." One exposed key plus missing auth can turn into customer trust damage," support load," and an emergency rebuild later."
References
- https://roadmap.sh/api-security-best-practices
- https://roadmap.sh/code-review-best-practices
- https://roadmap.sh/qa
- https://nextjs.org/docs/app/building-your-application/authentication
- https://vercel.com/docs/environment-variables
---
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.*
Cyprian Tinashe Aarons — Senior Full Stack & AI Engineer
Cyprian helps founders rescue, secure, deploy, and automate AI-built apps with production-grade engineering, launch systems, and AI integration.