- Symptom
- A secret API key, such as an OpenAI, Stripe secret or Supabase secret key, is named NEXT_PUBLIC_ somethingThe key's value can be found by searching the built JavaScript or the browser's developer tools
- Cause
- Next.js inlines NEXT_PUBLIC_ variables at build time, replacing each reference with the literal value in any JavaScript sent to the browser. Variables without the prefix are only available on the server. Adding the prefix to make a value readable in a client component therefore publishes it.
- Fix
- Remove the NEXT_PUBLIC_ prefix from every secret and read it only in server code, such as Route Handlers, Server Actions or Server Components, and have the browser call your server instead. Treat any secret that was ever built with the prefix as leaked and rotate it with its provider.
- Apply
// Before: shipped to every visitor // const openai = new OpenAI({ apiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY }) // After: app/api/chat/route.ts runs only on the server import OpenAI from 'openai' const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }) export async function POST(request: Request) { // check the session and rate limit here, then call the model }- Affected
- Next.js 9.4 and later, any variable whose name starts with NEXT_PUBLIC_
- Sources
Last verified 2026-10-27 · Confirmed by 0 builders