Exposed API Keys in V0 Code
V0 generates React components that developers integrate into Next.js applications. While V0 itself does not have access to your API keys, it generates code patterns that encourage developers to place secrets in frontend code, especially when building components that interact with external services.
Scan Your v0 AppHow It Happens
V0 generates frontend components that sometimes include fetch calls to external APIs. When a developer prompts V0 for a "weather widget" or "AI chat component," the generated code includes API call patterns with placeholder values like YOUR_API_KEY_HERE. Developers replace these placeholders with real keys directly in the component rather than moving the call to a server-side route. V0 components are React client components by default. When developers add API calls to these components, the API key must be available in the browser. This leads developers to use NEXT_PUBLIC_ environment variables for keys that should be server-only. Because V0 generates self-contained components, the pattern of putting everything (rendering, data fetching, API calls) in a single file feels natural. This co-location makes it easy to keep the API key in the same file as the UI, rather than separating data fetching into a server component or API route.
Impact
API keys embedded in V0-generated client components are visible to anyone who inspects the page source or JavaScript bundle. For paid services like OpenAI, Anthropic, or Google Maps (beyond the free tier), this results in direct financial loss as attackers consume the API quota. If the exposed key provides access to user data (like a database key or admin API), attackers can extract sensitive information from the backend service. The frontend component gives them the access token they need. Keys exposed in Next.js client components are especially persistent because Next.js pre-renders pages and caches them. The key may appear in static HTML, server-rendered output, and cached CDN responses, making it harder to fully remove even after the code is fixed.
How to Detect
Search your Next.js project for NEXT_PUBLIC_ environment variables and verify each one is truly safe to expose. Supabase anon keys and Firebase API keys are fine; OpenAI, Stripe secret, or database keys are not. Inspect V0-generated components for fetch calls or SDK initializations that include API keys. Check whether these calls happen in a client component ('use client' directive) or a server component. Vibe App Scanner detects API keys in deployed Next.js applications by analyzing both the static HTML and JavaScript bundles, catching keys exposed through client-side rendering, server-side rendering, and static generation.
How to Fix
Move API calls from V0-generated client components to Next.js Server Actions or API Route Handlers. The client component calls a server function, and the server function holds the secret key. Convert data-fetching V0 components from client components to server components where possible. Server components run on the server and never send their code to the browser, keeping API keys secure. Create a pattern in your project where V0 components handle only rendering, and data fetching is done in parent server components or server actions. This separation makes it natural to keep keys server-side. Audit your .env.local file and remove NEXT_PUBLIC_ prefixes from any secret values. Use server-side environment variables (without the prefix) and access them only in server components, API routes, or Server Actions.
Code Examples
Weather widget from V0
// V0-generated client component with API call
'use client'
export function WeatherWidget({ city }: { city: string }) {
const [weather, setWeather] = useState(null)
useEffect(() => {
fetch(`https://api.weather.com/v1?key=${process.env.NEXT_PUBLIC_WEATHER_KEY}&city=${city}`)
.then(r => r.json())
.then(setWeather)
}, [city])
return <div>{weather?.temp}°</div>
}// Server Action handles the API call
'use server'
export async function getWeather(city: string) {
const res = await fetch(
`https://api.weather.com/v1?key=${process.env.WEATHER_KEY}&city=${city}`
)
return res.json()
}
// Client component calls the server action
'use client'
export function WeatherWidget({ city }: { city: string }) {
const [weather, setWeather] = useState(null)
useEffect(() => {
getWeather(city).then(setWeather)
}, [city])
return <div>{weather?.temp}°</div>
}Frequently Asked Questions
Does V0 have access to my API keys?
No. V0 generates code with placeholders. The risk comes when developers replace placeholders with real keys in client-side code rather than moving the API call to a server component or API route.
Are NEXT_PUBLIC_ variables always unsafe?
NEXT_PUBLIC_ variables are exposed to the browser by design. Use them only for values that are safe to be public (Supabase anon key, Firebase API key, public analytics IDs). Never use them for secret API keys.
Can I use V0 components with server-side data fetching?
Yes. Pass data to V0 components as props from a parent server component, or use Next.js Server Actions to fetch data. This keeps API keys on the server while letting V0 components handle the UI rendering.
Related Security Resources
Is Your App Vulnerable?
VAS automatically scans for exposed api keys and other security issues in v0 apps. Get actionable results with step-by-step fixes.
Scans from $5, results in minutes.