A secret is exposed when anyone outside your team can read it: in your website’s code, in a public or shared repository, in a screenshot, or in an old commit. AI-built apps leak secrets for a simple reason: the tools optimise for “make it work”, and the quickest way to make a payment or email feature work is often to paste the key where the browser can see it. This post explains which keys are meant to be public, how to find the ones that are not, and what to do in the first hour if you find one.
What counts as a “secret” in a small app?
A secret is any value that lets its holder act as your app rather than as a visitor. Typical examples are payment provider secret keys, database admin keys, email and SMS service keys, AI model API keys, and database connection strings.
Not every key is a secret. Many services issue two kinds: a public key designed to sit in the browser and a secret key that must stay on a server. Supabase is a good example. Its publishable key is safe in shipped code because “it only reaches what Row Level Security allows”, while a secret key “bypasses every Row Level Security policy you have” and should never be put “in a browser, a shipped application, or source control” (Supabase API keys docs). The public key is only safe if your database rules are right, which we cover in Supabase row level security for AI-built apps.
How do secrets end up in the browser?
Most modern web frameworks let you mark a setting as safe for the browser by giving it a prefix. Vite exposes any variable starting with VITE_ “in client-side source code after Vite bundling” and warns that these “should not contain sensitive information such as API keys” (Vite docs). Next.js does the same for variables starting with NEXT_PUBLIC_, which it inlines “into any JavaScript sent to the browser” (Next.js docs).
When an AI assistant hits an error like “variable is undefined in the browser”, a common fix is to add that prefix. The error goes away and the secret is now shipped to every visitor. Nothing breaks, so nobody notices.
The other common path is the code itself. Ask an AI tool to “connect to Stripe” and it may paste the key directly into a file. That file is then committed, pushed and sometimes shared.
How big is the problem?
Large. GitGuardian counted 23.8 million secrets leaked on public GitHub repositories in 2024, a 25% increase on the year before. It also found that 70% of secrets leaked in 2022 were still active, and that 35% of the private repositories it examined contained secrets (GitGuardian, 2025). A private repository is not a safe place for a key; it only narrows who can find it.
In AI-built apps specifically, a security researcher’s scan of Lovable-built sites found 303 endpoints across 170 projects without proper row level security, and the exposed data included API keys for services such as Gemini and Google Maps alongside user records (Superblocks, 2025). The issue was later recorded as CVE-2025-48757; Lovable disputes the CVE on the grounds that each customer is responsible for protecting their own app’s data.
How can you check your own app in 20 minutes?
You can do most of this without writing code.
- Read your live site’s source. Open your app, right-click, choose “View page source”, then open your browser’s developer tools and look at the loaded JavaScript files. Search for
secret,sk_live,sk_test,service_role,password,api_keyandtoken. Note anything that looks like a long random string next to one of those words. - List your environment variables. In your hosting dashboard, list every variable. Any with a
VITE_,NEXT_PUBLIC_,PUBLIC_orEXPO_PUBLIC_prefix is visible to visitors. Check each one against the provider’s documentation: is it the public key or the secret one? - Search your repository history, not just today’s files. A key removed last month is still in old commits. A secret scanner such as GitGuardian’s tools or Yelp’s detect-secrets, which the OWASP guidance names as a mature option (OWASP Secrets Management Cheat Sheet), will scan the whole history.
- Check where the code has been shared. Forks, zip files sent to contractors, screenshots in support tickets, pasted snippets in chat tools. If a key went there, treat it as exposed.
You found an exposed key. What now?
Revoke first, investigate second. The OWASP guidance is blunt: keys that were exposed “should undergo immediate revocation” (OWASP). Work through the steps in this order:
- Create a new key and revoke the old one in the provider’s dashboard. Deleting the key from your code does nothing to a copy someone already has. Supabase notes that an attacker can “still use the key from other tools” even if the browser blocks it (Supabase).
- Put the new key somewhere only your server can read: your host’s encrypted environment settings or a secrets manager, without a public prefix.
- Move any browser code that used the secret behind a small server function. The browser asks your server; your server holds the key and calls the provider.
- Check the provider’s logs for use you do not recognise: unexpected charges, emails, AI usage or database reads. Note the dates.
- Clean up the old key from code and, if needed, from repository history. This matters less than revocation, because a revoked key is useless.
- Decide whether personal data was exposed. If the key gave access to user data, you may have obligations to report. In India, the DPDP Rules 2025 require a breach report to the Data Protection Board and notice to affected people, with those duties phasing in by May 2027 (AMS Shardul, 2025). Take advice early.
How do you stop it happening again?
Prevention is mostly habit and a couple of free tools.
- Turn on push protection. GitHub’s push protection blocks pushes that contain recognisable credentials. For users it is on by default for public repositories, but protection at the repository level is off by default and must be enabled by an owner (GitHub docs).
- Add a pre-commit scanner so secrets are caught on the laptop, before they reach any repository.
- Give your AI tool a standing rule: “Never put secret keys in client code or in any variable with a public prefix. Ask me where secrets should live.” It will not always follow it, which is why review still matters.
- Use the narrowest key that works. Many providers let you create restricted keys that can only do one thing. A leaked restricted key does less damage.
- Rotate on a schedule, so a key that leaks quietly stops working on its own (OWASP).
Secrets are one item on a longer list. Our production readiness checklist for vibe-coded apps covers the other eleven, and our guide to backup and restore testing covers what to do if a leaked key was used to damage data.
Want a second pair of eyes?
Our free production check includes a search for exposed secrets in your live site and code history, along with security, backups, environments and privacy. You get a call, a written report and a quote. See how we help teams with AI-built apps.
Sources
- Supabase, Understanding API keys
- Vite, Env variables and modes
- Next.js, Environment variables guide
- GitGuardian, The State of Secrets Sprawl 2025
- Superblocks, Lovable RLS vulnerability explained
- SentinelOne, CVE-2025-48757 entry
- OWASP Secrets Management Cheat Sheet
- GitHub, About push protection
- AMS Shardul, Enforcement of the DPDP Act and notification of the DPDP Rules