How I Would Fix exposed API keys and missing auth in a Vercel AI SDK and OpenAI marketplace MVP Using Launch Ready.
If your Vercel AI SDK and OpenAI marketplace MVP has exposed API keys and missing auth, I would treat that as a production incident, not a normal bug. The...
Opening
If your Vercel AI SDK and OpenAI marketplace MVP has exposed API keys and missing auth, I would treat that as a production incident, not a normal bug. The symptom is usually simple: users can hit sensitive endpoints without signing in, and secrets are either visible in the client bundle, browser network tab, repo history, or Vercel environment setup.
The most likely root cause is that the app was built fast with serverless functions and client-side calls, then auth was added late or skipped. The first thing I would inspect is the request path from browser to API route, then I would check whether any OpenAI key or privileged token is being shipped to the frontend or logged in plain text.
Triage in the First Hour
1. Check the live app in an incognito window.
- Try every marketplace action without logging in.
- Confirm which pages, API routes, and server actions are actually protected.
2. Inspect Vercel deployment logs.
- Look for requests to sensitive routes from anonymous users.
- Look for stack traces, env var names, or debug output containing secrets.
3. Review the browser network tab.
- Confirm whether any request includes an OpenAI key, internal token, or admin header.
- Check if the frontend is calling OpenAI directly instead of going through a server route.
4. Audit Vercel environment variables.
- Verify which variables are set at Production, Preview, and Development.
- Confirm nothing secret is marked as `NEXT_PUBLIC_` or otherwise exposed to the client.
5. Check repo history and recent commits.
- Search for hardcoded keys, test tokens, `.env` files, and copied examples.
- Review whether a recent AI-generated change introduced unsafe client-side access.
6. Inspect auth middleware and route guards.
- Confirm protected pages are actually blocked at the edge or server layer.
- Make sure authorization is enforced on the API route itself, not only in the UI.
7. Review OpenAI account usage.
- Look for unusual spikes in requests, tokens, or spend.
- If abuse is possible, rotate keys before doing anything else.
8. Check third-party integrations.
- Verify whether webhook handlers or marketplace actions trust user-supplied IDs without verification.
- Confirm role checks exist for admin-only actions like publishing listings or editing payouts.
9. Freeze risky changes.
- Pause deploys until you know where the leak starts and where auth breaks.
- If needed, disable public write endpoints temporarily.
10. Capture evidence before changing code.
- Save screenshots of exposed screens and logs.
- Note timestamps so you can match them to deployments and commits.
Root Causes
| Likely cause | What it looks like | How I confirm it | |---|---|---| | OpenAI key used in client code | Key appears in browser bundle or network request | Search for `OPENAI_API_KEY` in frontend files and inspect built JS | | Missing server-side auth guard | Unauthenticated users can call protected routes | Hit each route directly with no session cookie | | UI-only auth protection | Pages hide buttons but APIs still work | Bypass UI and call backend endpoints manually | | Misconfigured env vars on Vercel | Secret marked public or copied into preview build | Compare env var names across environments | | Weak role checks | Any signed-in user can perform admin actions | Test non-admin account against sensitive endpoints | | Leaked secret in logs or repo history | Key appears in logs, commit diff, or old file versions | Search git history and deployment logs |
A common pattern with Vercel AI SDK apps is this: the developer protects the page visually but forgets to protect `/api/chat`, `/api/generate`, or a server action. Another common pattern is using OpenAI directly from React because it feels faster during MVP buildout.
The Fix Plan
1. Revoke exposed keys immediately.
- Rotate the OpenAI API key first if there is any chance it reached the browser, logs, or git history.
- Rotate any related service tokens too: database admin credentials, webhook secrets, and email provider keys if they were touched.
2. Move all OpenAI calls behind server-side code.
- The browser should never talk to OpenAI with a private key.
- Use a server route or server action that holds the secret only on the backend.
3. Add hard auth checks at every sensitive entry point.
- Protect routes on both the page layer and API layer.
- Require session validation before reading data, creating listings, generating content, or accessing admin tools.
4. Add authorization checks by role and ownership.
- A signed-in user should only see their own marketplace data unless they are explicitly an admin.
- Verify ownership in the database query itself where possible.
5. Remove secret leakage paths.
- Strip secrets from logs, error messages, analytics events, and debug responses.
- Search for accidental exposure in console output and structured logs.
6. Lock down Vercel environment variables.
- Keep private keys server-only.
- Use separate values for production and preview if needed, but do not duplicate privileged credentials into places that do not need them.
7. Put middleware in front of protected areas only if it helps clarity.
- Middleware can help redirect unauthenticated users early.
- It does not replace backend authorization checks.
8. Add rate limits to expensive endpoints.
- AI generation endpoints should be throttled to prevent abuse and surprise spend spikes.
- Even basic per-user limits reduce damage if auth ever fails again.
9. Tighten CORS only if cross-origin access exists.
- If your app does not need cross-origin requests from other domains, keep CORS strict or avoid exposing it at all.
10. Deploy a clean fix rather than patching around bad architecture forever.
- I would prefer one safe refactor over five band-aids that still leave secrets exposed.
A minimal pattern I would expect looks like this:
import { getServerSession } from "next-auth";
import { openai } from "@ai-sdk/openai";
export async function POST(req: Request) {
const session = await getServerSession();
if (!session?.user?.id) {
return new Response("Unauthorized", { status: 401 });
}
const { prompt } = await req.json();
if (!prompt || prompt.length > 4000) {
return new Response("Invalid input", { status: 400 });
}
// Call OpenAI only on the server
// using a secret stored in Vercel env vars
}The exact auth library can differ, but the rule does not change: no private model keys in client code, no sensitive action without server-side authz checks.
Regression Tests Before Redeploy
1. Anonymous access tests
- Try every protected route without signing in.
- Acceptance criteria: all sensitive endpoints return `401` or redirect correctly; no data leaks through page source or network calls.
2. Role-based access tests
- Use a normal user account against admin functions like listing moderation or payout settings.
- Acceptance criteria: non-admin users get `403` on restricted actions.
3. Secret exposure tests
- Search built assets for `OPENAI_API_KEY`, database URLs with credentials removed? no credentials should appear at all except masked placeholders in docs/templates only where safe to show generic examples are acceptable? Better: search bundles/logs for actual secret values after build/deploy staging run only? Actually use placeholder search patterns plus grep current repo/history for accidental references."
Wait final must be coherent; continue.]
Delivery Map
References
- [roadmap.sh - API security](https://roadmap.sh/api-security-best-practices)
- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/)
- [MDN Web Docs - HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
- [Cloudflare DNS documentation](https://developers.cloudflare.com/dns/)
- [Sentry documentation](https://docs.sentry.io/)
---
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.