How to Fix API Key Exposure in Netlify Apps
Netlify apps may expose API keys through hardcoded values in frontend code or secrets stored in netlify.toml (which is committed to git). This guide helps you find, rotate, and properly secure exposed keys using Netlify environment variables.
Find security issues automatically before attackers do.
Follow These Steps
Search for exposed secrets
Check both source code and configuration files.
grep -rn "sk-\|api_key\|apiKey\|secret" src/ netlify.toml --include="*.ts" --include="*.js" --include="*.toml"Check netlify.toml for secrets
The netlify.toml file is committed to git and should never contain secret values.
# BAD - secrets in netlify.toml (committed to git)
[build.environment]
OPENAI_API_KEY = "sk-proj-secret"
# GOOD - only non-secret config in netlify.toml
[build.environment]
NODE_VERSION = "20"Rotate compromised keys and add to Netlify dashboard
Generate new keys at each provider, then add them in the Netlify dashboard under Site settings > Environment variables.
Mark variables as "Secret" to prevent them from appearing in build and function logs.
Use Netlify Functions for sensitive API calls
Move API calls that require secrets to Netlify Functions.
// netlify/functions/api-proxy.ts
import { Handler } from '@netlify/functions'
export const handler: Handler = async (event) => {
const apiKey = process.env.OPENAI_API_KEY
const body = JSON.parse(event.body || '{}')
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
})
return {
statusCode: 200,
body: JSON.stringify(await response.json())
}
}Update frontend to call Netlify Functions
Replace direct API calls with calls to your serverless functions.
// Before (INSECURE)
fetch('https://api.openai.com/v1/...', {
headers: { 'Authorization': 'Bearer sk-proj-EXPOSED' }
})
// After (SECURE)
fetch('/.netlify/functions/api-proxy', {
method: 'POST',
body: JSON.stringify({ prompt: userInput })
})Deploy and verify
Deploy and run a VAS scan to confirm no secrets are in the frontend bundle.
What You'll Achieve
All secrets are removed from netlify.toml and source code, stored in Netlify environment variables, and accessed only through Netlify Functions. Your frontend bundle contains no sensitive credentials.
Common Mistakes to Avoid
Mistake
Putting secrets in netlify.toml build environment
Fix
netlify.toml is committed to git. Use the Netlify dashboard for secrets instead.
Mistake
Using VITE_ or NEXT_PUBLIC_ prefix for secrets in Netlify
Fix
These prefixes embed variables in the client bundle. Use unprefixed names and access them only in Netlify Functions.
Frequently Asked Questions
Are Netlify environment variables secure?
Yes. Variables set in the Netlify dashboard are encrypted and only available at build time and in serverless functions. They are not embedded in static site output unless your framework exposes them.
Can I use different secrets for deploy previews?
Yes. Netlify lets you scope environment variables to different deploy contexts (production, deploy previews, branch deploys). Use test keys for previews.
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