If we had to pick one security problem to warn every founder about before they launch, it would be exposed API keys. Not SQL injection, not weak passwords, not missing rate limiting. Exposed api keys and secrets in code. We see it in roughly half the assessments we run, and it is often sitting in plain view once you know where to look. The scary part is that most founders never look, because nothing about the app appears broken. It works fine right up until someone with bad intentions finds the key first.
Why AI tools leak keys
AI coding assistants are optimised to make your app run, not to make it safe. When you ask for a feature that calls Stripe, OpenAI, SendGrid, or a mapping API, the fastest way to get something working is to paste the key directly into the code that needs it. That is exactly what tools like Cursor, Bolt, Lovable, and Replit Agent tend to do by default, especially early in a project when you are just trying to see something work on screen.
Environment variables, secret managers, and server-side proxying all add friction. They require a build step, a deployment config, sometimes a whole backend the AI hasn’t been asked to build yet. So the model takes the path of least resistance: it puts the key where the code can reach it right now. That usually means inside a front-end component, a config file that gets committed, or a request made directly from the browser. The app works. The demo looks great. Nobody notices the key is sitting there in the JavaScript until it’s too late.
We wrote more broadly about this pattern in our vibe code security guide, and exposed secrets show up again on our list of common bugs in AI-generated code. It is not a rare edge case. It is close to a default outcome unless someone actively prevents it.
Where they hide
The first place to check is your front-end JavaScript bundle. Any key referenced with a VITE_, NEXT_PUBLIC_, or similar public prefix, or any key hardcoded straight into a component, ships to every visitor’s browser. Open your site, view the page source, or look in the Network tab of your browser’s dev tools, and search the loaded scripts for words like “key”, “secret”, “token”, or the name of a service you use, such as “stripe” or “openai”. If a full key appears in that search, it is public. Anyone can copy it.
The second place is git history. Founders often catch a leaked key, remove it from the current file, and assume the problem is solved. It isn’t. If that key was ever committed, it still lives in every earlier commit unless the history itself was rewritten. Public repositories are actively scanned by bots looking for exactly this pattern, and even private repos aren’t a guarantee if access has ever been shared loosely.
The third place is configuration files that get pushed alongside your code by mistake: .env files without a proper .gitignore entry, config.json, deployment manifests, or serverless function definitions. AI tools frequently generate a .env.example correctly but then also commit the real .env right next to it, because nobody told the model that one file is a template and the other is live.
How to find yours without reading code
You don’t need to be a developer to run this check yourself, and we’d encourage you to do it today rather than waiting for a formal review.
Start with your live site. Open it in a browser, right-click, choose “View Page Source,” and press Ctrl+F (or Cmd+F on a Mac) to search for “key”, “secret”, “sk-”, “pk_live”, or “token”. Do the same in the Network tab while the page loads and while you use the app’s main features, since some keys only appear in requests fired after an action, not in the initial page load.
Next, check your GitHub or GitLab repository’s search function. Most platforms let you search across the whole repo, including history, for specific strings. Search for the same terms, plus the names of any services you use: “stripe”, “sendgrid”, “openai”, “aws”, “supabase”. If your project is connected to GitHub, GitHub’s own secret scanning will sometimes flag exposed keys automatically and email you, so check your notifications and security alerts tab too.
If none of that turns anything up but you’re still uneasy, that unease is worth acting on. Our guide on reviewing AI-generated code without being a developer covers other checks worth running in the same sitting, and a professional assessment will catch things a manual search misses, particularly keys buried in server logs or third-party webhook configs.
What to do the moment you find one
Rotate it immediately. Every service that issues API keys, Stripe, OpenAI, AWS, SendGrid, Supabase, has a dashboard page where you can revoke the exposed key and generate a new one. Do this before you fix the code, not after, because the old key is compromised the second it becomes public and every minute it stays active is a minute someone else can use it.
Once the key is rotated, check your usage logs and billing dashboard for anything unexpected. Unusual charges, spikes in API calls, or requests from unfamiliar locations are all signs the key was already being used by someone else. Some services let you set spending caps or usage alerts, and if you don’t have those configured, this is the moment to add them.
Then fix the underlying cause, not just this one instance. If the key was hardcoded in the front end, that call needs to move to a server-side function where the key never reaches the browser. If it was committed to git, the history needs cleaning, not just the current file. This is exactly the kind of thing that gets missed when an app is built fast and never properly reviewed, and it’s a big part of why we talk about the gap between something that runs and something that’s actually production code.
Preventing it next time
The fix that actually holds is structural. Every secret should live in environment variables that are never committed, with a .gitignore entry in place from the very first commit, not added after the fact. Any API call that requires a private key belongs on the server, called from a backend function, never directly from the browser. If you’re using a platform like AWS Amplify or Vercel, use their built-in environment variable management rather than typing secrets into code at all.
It’s also worth asking your AI tool directly, before you start a session, to never hardcode credentials and to always use environment variables for anything sensitive. It won’t catch everything, but it changes the default behaviour more often than you’d expect. Beyond that, a periodic check, even a quick manual one like the search above, costs you ten minutes and can save you from a very expensive surprise on your next bill.
Think a key might be exposed? We’ll find it fast. Get a free assessment and we’ll tell you exactly what’s at risk.