How to Fix API Key Exposure in Windsurf Apps
Windsurf can embed API keys directly in source files during rapid prototyping. If those keys reach production, they are visible to anyone inspecting your JavaScript bundle. This guide helps you find every exposed key, rotate it, and set up secure secret management.
Find security issues automatically before attackers do.
Follow These Steps
Audit your project for hardcoded secrets
Search all source files for API key patterns and credential strings.
grep -rn "sk-\|api_key\|apiKey\|secret\|password\|token" src/ --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx"Check environment variable usage for misconfigurations
Verify that no secret keys are being exposed via client-side environment variable prefixes.
# Find client-exposed env vars that might be secrets
grep -rn "NEXT_PUBLIC_.*KEY\|NEXT_PUBLIC_.*SECRET\|VITE_.*SECRET" src/ .env*Rotate all compromised keys at the provider
Generate new keys from each API provider dashboard and deactivate old ones immediately.
Set up proper .env configuration
Create environment files with the correct variable naming conventions for your framework.
# .env.local (for Next.js)
OPENAI_API_KEY=sk-proj-new-key # Server-side only
DATABASE_URL=postgresql://... # Server-side only
NEXT_PUBLIC_APP_URL=https://... # Safe for client
# .gitignore
.env
.env.local
.env.productionMove API calls to server-side routes
Create API routes that handle third-party API calls server-side.
// app/api/generate/route.ts
export async function POST(req: Request) {
const session = await auth()
if (!session) return Response.json({ error: 'Unauthorized' }, { status: 401 })
const { prompt } = await req.json()
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ model: 'gpt-4o', messages: [{ role: 'user', content: prompt }] })
})
return Response.json(await response.json())
}Deploy and verify
Deploy your fixes and run a VAS scan to confirm no keys are exposed.
Check the browser Sources tab in DevTools to verify no secrets appear in the client-side JavaScript.
What You'll Achieve
All API keys are rotated, moved to server-side environment variables, and API calls are proxied through server-side routes. Your Windsurf app no longer exposes secrets to the browser.
Common Mistakes to Avoid
Mistake
Using VITE_ prefix for secret keys in Vite projects
Fix
VITE_ prefix exposes variables to the browser. Use non-prefixed names for secrets and access them only in server-side code.
Mistake
Only fixing the code without rotating compromised keys
Fix
Any key that was in frontend code is compromised. Rotate it at the provider before deploying the fix.
Frequently Asked Questions
Which environment variable prefixes expose secrets to the browser?
NEXT_PUBLIC_ in Next.js and VITE_ in Vite expose variables to the client bundle. Never use these prefixes for secret API keys.
Can I use a .env file safely with Windsurf?
Yes, but add .env to .gitignore before your first commit. Variables without client-safe prefixes (NEXT_PUBLIC_, VITE_) remain server-side only.
How do I prevent Windsurf from generating code with hardcoded keys?
Use project rules or a windsurf-rules file to instruct the AI to always use environment variables. Avoid pasting real keys into the chat context.
Ready to Secure Your App?
VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.
Start Security Scan