Your NEXT_PUBLIC secret is already in the browser bundle A developer has highlighted a critical security flaw in Next.js applications where developers inadvertently expose server-side secrets by prefixing environment variables with NEXT_PUBLIC_. The tool KeyDrift performs a read-only scan of client bundles to detect such leaks, cross-referencing credentials with the tool that introduced them. The developer recommends moving secret usage to server-side code and running a clean build to mitigate the risk. In a Next.js app it’s easy to slip a secret e.g., STRIPE SECRET KEY , OpenAI API key, Supabase JWT into a client‑side bundle. When a server component reads process.env.STRIPE SECRET KEY it stays on the server, but copying that line into a client component causes the build to fail to resolve the variable. The common “quick fix”—renaming the variable with the NEXT PUBLIC prefix—makes the value part of the JavaScript that every visitor downloads, turning a server‑only secret into a public leak. Next.js environment variable scoping NEXT PUBLIC prefix are stripped from the client bundle at build time. They are only available in server‑side code pages/api/ , server components, getServerSideProps , etc. . NEXT PUBLIC prefix are injected into the client bundle and can be read from process.env in any browser‑executed code. Accidental exposure const stripeKey = process.env.STRIPE SECRET KEY; from a server component to a client component or a shared utility imported by both . STRIPE SECRET KEY is undefined on the client. NEXT PUBLIC STRIPE SECRET KEY . Why the leak is critical KeyDrift performs a read‑only scan of your client bundle—no credentials are required—to locate hard‑coded secrets and environment variables that have been inlined. The scan cross‑references each detected credential with the tool that introduced it e.g., Next.js, Replit, Cursor . Typical output for a Next.js leak looks like: Critical STRIPE SECRET KEY found in client bundle tool: Next.js Location: static/chunks/pages/ app.js:1234 Recommendation: Move usage to a server component or API route. KeyDrift also flags variables that have been renamed with the NEXT PUBLIC prefix and marks them as high or critical depending on the credential type e.g., Stripe secret key → critical . python // app/api/stripe/checkout/route.ts server‑only import Stripe from 'stripe'; const stripe = new Stripe process.env.STRIPE SECRET KEY , { apiVersion: '2023-10-16', } ; export async function POST req: Request { // server‑side logic only } js // app/components/CheckoutButton.tsx client component 'use client'; import { useState } from 'react'; export default function CheckoutButton { const loading, setLoading = useState false ; const startCheckout = async = { setLoading true ; const res = await fetch '/api/stripe/checkout', { method: 'POST' } ; // handle response... setLoading false ; }; return