How I Would Fix exposed API keys and missing auth in a Vercel AI SDK and OpenAI founder landing page Using Launch Ready.
The symptom is usually obvious: the landing page works, but the browser network tab shows OpenAI requests, exposed env values, or a client-side key that...
How I Would Fix exposed API keys and missing auth in a Vercel AI SDK and OpenAI founder landing page Using Launch Ready
The symptom is usually obvious: the landing page works, but the browser network tab shows OpenAI requests, exposed env values, or a client-side key that should never be public. The deeper problem is usually twofold: secrets were shipped into the frontend bundle, and there is no real auth or server-side gate around the AI action.
The first thing I would inspect is the actual request path. I want to know whether the page is calling OpenAI directly from the browser, whether Vercel env vars are being bundled into client code, and whether any user can hit the AI endpoint without being authenticated or rate-limited.
Triage in the First Hour
1. Check the live page in Chrome DevTools.
- Open Network and look for requests to OpenAI or your AI route.
- Confirm whether the request originates from the browser or from a serverless function.
- Look for leaked headers, query params, or response bodies that reveal secrets.
2. Inspect the deployed build output.
- Review `.next`, Vercel deployment logs, and build warnings.
- Search for `OPENAI_API_KEY`, `VERCEL_`, or any secret-like value in client bundles.
- Confirm whether any env var was prefixed with `NEXT_PUBLIC_`.
3. Review Vercel project settings.
- Check Environment Variables for production, preview, and development scopes.
- Verify which branches deploy to production.
- Confirm whether old secrets are still present after rotation.
4. Check auth state on every AI route.
- Open the API route or server action used by Vercel AI SDK.
- Confirm there is session validation before any model call.
- Verify that anonymous users cannot trigger unlimited requests.
5. Inspect logs and monitoring.
- Review Vercel function logs for spikes, repeated calls, and errors.
- Check uptime monitoring and error tracking for failed requests.
- Look for 401, 403, 429, and 5xx patterns.
6. Audit connected accounts.
- Rotate OpenAI keys if exposure is confirmed.
- Revoke any unused keys immediately.
- Verify Cloudflare DNS and SSL are correctly pointed at the current deployment.
7. Review all files touched by recent AI-generated changes.
- Focus on app routes, API routes, server actions, config files, and env usage.
- Search for hardcoded tokens or copied examples from docs that were never cleaned up.
8. Confirm email and domain setup if this page collects leads.
- Check SPF, DKIM, and DMARC so lead emails do not land in spam.
- Verify redirects and canonical domain behavior so you are not sending traffic to stale pages.
grep -R "OPENAI_API_KEY\|NEXT_PUBLIC_\|sk-" . --exclude-dir=node_modules --exclude-dir=.next
Root Causes
| Likely cause | What it looks like | How I confirm it | |---|---|---| | Client-side OpenAI call | Browser calls OpenAI directly | Network tab shows requests leaving from frontend code | | Secret exposed in bundle | Key appears in JS chunk or source map | Grep build output or search deployed JS for secret strings | | Missing auth on AI route | Anyone can POST to `/api/chat` | Incognito test succeeds without login | | Weak env handling | Same key used across dev and prod | Vercel env scopes show one shared secret everywhere | | Over-permissive logging | Secrets appear in logs or error traces | Function logs include headers, payloads, or env values | | No rate limiting | Bot traffic burns tokens fast | Logs show repeated calls from same IP or user agent |
The most common founder mistake is assuming "the API route is private" just because it lives under `/api`. It is not private unless you add authentication, authorization checks, input validation, and rate limits.
Another common issue is using `NEXT_PUBLIC_` by habit because it makes debugging easier. That prefix tells Next.js to ship the variable to every browser session. If it contains a secret or anything that can be abused, it is already lost.
The Fix Plan
1. Stop the leak first.
- Rotate every exposed OpenAI key immediately.
- Remove compromised keys from Vercel environment variables before redeploying.
- If source maps are public and contain sensitive data, disable them until fixed.
2. Move all model calls server-side only.
- The browser should call your own API route or server action.
- That server code should hold the OpenAI key in a non-public environment variable.
- Never pass raw provider keys into client components.
3. Add authentication before any AI action runs.
- Require a valid session for protected routes.
- For founder landing pages with gated tools like waitlist generation or demo chat, block anonymous access unless you explicitly want public usage.
- If public access is required for marketing reasons, add strict rate limits plus bot protection.
4. Validate inputs before sending them to OpenAI.
- Limit prompt length and strip unexpected fields.
- Reject empty payloads, oversized messages, and malformed JSON early.
- Treat user content as untrusted data even if it comes from your own form.
5. Add authorization rules where needed.
- If there are admin-only prompts or internal tools, check role membership on the server side.
- Do not rely on hidden buttons in the UI as a security boundary.
6. Lock down logging and error handling.
- Never log full prompts if they may contain personal data or secrets.
- Return generic errors to users and detailed traces only to secure observability tools.
- Remove debug prints before redeploying.
7. Add rate limiting at the edge or API layer.
- Limit requests per IP or per authenticated user session.
- Start with something practical like 10 requests per minute per user for a landing-page assistant.
- Block obvious abuse before it reaches OpenAI billing.
8. Redeploy with clean environment separation.
- Use separate dev, preview, and production keys where possible.
- Confirm production only points at production services and production domains.
9. Add Cloudflare protections if traffic is public-facing. - Use WAF rules where appropriate - Enable DDoS protection - Cache static assets aggressively - Keep dynamic AI endpoints uncached
10. Document what changed before handover. - List rotated secrets - Record new auth rules - Note which routes are public versus protected - Include rollback steps
If I were doing this as Launch Ready work, I would treat it as a production safety sprint rather than a cosmetic fix. The goal is not just "make it work again". The goal is to stop token leakage, prevent unauthorized usage, protect ad spend from abuse, and make sure launch traffic does not create support noise or surprise billing.
Regression Tests Before Redeploy
Use these checks before shipping:
1. Authentication checks
- Anonymous users cannot reach protected AI routes.
- Logged-in users can access only their allowed actions.
- Admin-only actions fail for non-admin accounts with a 403 response.
2. Secret exposure checks ```bash grep -R "sk-" .next/ dist/ build/ 2>/dev/null
3. Browser checks - No OpenAI key appears in DevTools sources or network responses - No secret-like values appear in rendered HTML 4. Functional checks - Form submits still work - Error states render cleanly when OpenAI fails - Loading states do not freeze the page 5. Abuse checks - Rapid repeated submissions trigger rate limiting - Oversized prompts are rejected safely - Invalid JSON does not crash the endpoint 6. Monitoring checks - Function logs show request IDs but no secrets - Uptime monitor pings return healthy status - Alerting fires on elevated 401s, 429s, or 5xxs Acceptance criteria I would use: - Zero secrets visible in client bundles or HTML source. - All protected AI endpoints require auth before model execution starts. - Rate limits block repeated abuse within 60 seconds of spike behavior detection work well enough for launch traffic of about 1k daily visitors without runaway cost risk). - P95 API response time stays under 800 ms before model latency; total user-visible response depends on OpenAI but should remain stable under normal load). - No critical console errors during smoke testing on mobile and desktop. ## Prevention The fix should not depend on memory or good intentions. I would put guardrails in place so this does not happen again. - Code review guardrails: -. Reject any diff that references `NEXT_PUBLIC_` for sensitive values -. Require all AI routes to pass through auth middleware or explicit session checks -. Review logging statements for leaked payloads - Security guardrails: -. Rotate provider keys every time exposure is suspected -. Keep least privilege on third-party accounts -. Use separate credentials for local dev and production - UX guardrails: -. Show clear login gates where access matters -. Add friendly error states when auth expires -. Make rate-limit messages understandable instead of cryptic - Performance guardrails: -. Keep static marketing content cached at Cloudflare -. Avoid unnecessary client-side rendering of sensitive workflows -. Watch bundle size so security fixes do not bloat LCP beyond roughly 2.5 seconds on mobile - Monitoring guardrails: -. Alert on unusual token usage spikes -. Track failed auth attempts by route -. Log request IDs so one bad deploy can be traced fast I also recommend a simple pre-release checklist: secrets scanned cleanly, auth verified manually with incognito mode, rate limits tested once per route family, rollback plan documented. That takes less than an hour and saves days of cleanup later. ## When to Use Launch Ready Use Launch Ready when you need this fixed fast without turning your landing page into a long engineering project. This sprint fits best when: - Your founder landing page already exists but feels unsafe to ship). - You need production deployment cleaned up before paid traffic starts). - You have exposed secrets) broken auth) messy env vars) or unclear ownership across tools). - You want one senior engineer to audit then fix rather than guess across five platforms). What you should prepare: - Access to Vercel), - Access to your domain registrar), - Access to Cloudflare if already connected), - OpenAI account access, - A list of all environments), - Any login provider details, - A short note describing who should be able to use each AI feature). My preference here is direct: fix security first) then launch polish). If you try to redesign copy) analytics) automation) while secrets are still exposed) you are spending money on top of risk instead of removing risk first). ## Delivery Map
flowchart TD A[Founder problem] --> B[cyber security audit] B --> C[Launch Ready sprint] C --> D[Production fixes] D --> E[Handover checklist] E --> F[Launch or scale]
## References 1. Roadmap.sh Cyber Security: https://roadmap.sh/cyber-security 2. Roadmap.sh API Security Best Practices: https://roadmap.sh/api-security-best-practices 3. Roadmap.sh QA: https://roadmap.sh/qa 4. Vercel Environment Variables: https://vercel.com/docs/projects/environment-variables 5. OpenAI API Security Best Practices: https://platform.openai.com/docs/guides/security --- ## 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.