Vulnerability Module
API Key Exposure: Detection and Remediation Guide
April 14, 2026 · 11 min read · PolyDefender Research Team
Leaked API credentials in client bundles, logs, source maps, and misconfigured environment variables — how to find them, rotate them, and prevent recurrence.
API key exposure is the most frequently detected critical vulnerability in AI-built applications. In PolyDefender's Q2 2026 dataset of 18,200 production scans, 31% of applications had at least one credential in a browser-accessible location. The consequence is direct and immediate: an attacker who finds an exposed key does not need to chain it with any other vulnerability. They have everything they need to access your data, impersonate your application, and in many cases, generate large financial charges.
How API Keys Get Exposed in AI-Built Apps
The most common exposure path in AI-generated code is the NEXT_PUBLIC_ or VITE_ environment variable prefix. These prefixes instruct Next.js and Vite to include the variable's value in the client-side JavaScript bundle, making it readable by anyone who loads the page. They exist for legitimate reasons — publishable API keys for analytics, payment widgets, and mapping services need to be accessible in the browser. They become critical vulnerabilities when applied to secrets that should only run server-side.
AI tools learn patterns from training data and codebases, and they have learned that NEXT_PUBLIC_ is a common way to access environment variables in frontend code. When an AI generates code that needs to call an external API, it sometimes generates an environment variable reference with this prefix applied to a key that should never be exposed.
Types of Exposed Keys: From Annoying to Catastrophic
Not all exposed keys carry the same risk. Understanding the blast radius of each key type helps you prioritize rotation.
- ▸**Supabase anon key**: Designed to be public; exposure is low risk if RLS is correctly configured, but catastrophic if RLS is missing
- ▸**Supabase service_role key**: Bypasses all RLS; exposure gives an attacker unrestricted database access — treat as maximum priority
- ▸**OpenAI API key**: Exposure allows unlimited model API calls billed to your account; attackers can run high-cost operations within minutes
- ▸**Stripe secret key**: Exposure allows reading all transaction data, modifying payout accounts, issuing refunds, and creating charges
- ▸**AWS access keys**: Exposure can result in compute cost explosion, data exfiltration from S3, and in worst cases complete infrastructure compromise
- ▸**SendGrid / Resend / Mailgun**: Exposure allows sending bulk email from your domain, damaging your sender reputation and potentially violating CAN-SPAM
Step 1: Detect Exposed Keys in Your Application
Start with your built JavaScript bundle. Every Next.js or React app compiles to one or more JavaScript files served to the browser. These files contain the content of any NEXT_PUBLIC_ or VITE_ variable that was defined at build time.
- ▸Open your production app in a browser, open DevTools → Sources, and find the main JavaScript bundle file
- ▸Use Ctrl+F to search for provider-specific prefixes: sk- (OpenAI, Stripe), SG. (SendGrid), AKIA (AWS), service_role, eyJ (base64-encoded JWT)
- ▸Also check your source map files if they are publicly accessible — append .map to your bundle URL to check
- ▸Run a PolyDefender scan on your production URL — the scanner specifically checks JavaScript bundles and source maps for credential patterns across 40+ provider formats
Step 2: Rotate and Revoke Immediately
Rotation is not optional and should not be delayed. If a key has been exposed, assume it has been found. Automated credential scrapers scan public repositories and JavaScript bundles continuously. GitHub reports that exposed secrets are typically accessed within 60 seconds of appearing in a public repository.
For each exposed key, go to the provider's dashboard and generate a new key before deleting the old one. Update your environment variables in your deployment platform (Vercel, Railway, Render) with the new key, then deploy. The old key should remain valid long enough for your deployment to complete, then delete it.
Step 3: Move Secrets to Server-Only Contexts
After rotating, fix the root cause: any secret that was browser-accessible must be moved to a server-only context.
- ▸In Next.js: remove the NEXT_PUBLIC_ prefix from any variable that should not be browser-readable. Server Components, API Routes, and Server Actions can access non-prefixed variables natively.
- ▸For operations that require a secret API key, move them to an API route or Server Action that runs server-side and returns only the data the frontend needs, never the raw API response or the key itself
- ▸In Vite applications: use import.meta.env variables without the VITE_ prefix for server-side operations, or proxy the API call through a server endpoint
Step 4: Add CI/CD Scanning to Prevent Recurrence
Rotation fixes the immediate incident. Preventing recurrence requires automated controls in your development and deployment pipeline.
- ▸Add Gitleaks or TruffleHog as a pre-commit hook to scan for credentials before any code is committed
- ▸Enable GitHub's secret scanning and push protection — it will block pushes that contain known credential patterns
- ▸Add a PolyDefender scan to your deployment pipeline so that each production deploy is automatically verified for new credential exposures
- ▸Set up spending alerts and rate limits on every provider so that if a key is exposed and used, the financial damage is bounded
Platform-Specific Notes
In **Lovable** apps: check every NEXT_PUBLIC_ variable in your Lovable project settings and in the deployed Vercel environment variables. Lovable's generated code sometimes copies admin Supabase client initialization patterns that include service_role keys.
In **Bolt.new** apps: check server-side handler files for inline credential strings. Bolt often initializes API clients with actual key values in the generated code to make it immediately functional.
In **v0** apps: check for source map exposure in Vercel deployments. v0-generated Next.js apps deploy to Vercel with default settings that may include source maps containing variable values.
Need a fast security baseline?
Run a free scan to detect secrets, auth bypass, RLS exposure, injection paths, and dependency risk in minutes.