If we could name one finding that shows up more than any other in audits of AI-built apps, it wouldn't be a subtle one. It would be secret keys — payment keys, AI-provider keys, database credentials — sitting in places where strangers can read them.
Why generators leak keys
It isn't carelessness, it's architecture. AI builders optimize for "it works in the demo," and the shortest path to working is calling an API directly from the browser — which requires shipping the key to the browser. The distinction between a publishable key (safe in client code) and a secret key (server-only, always) is exactly the kind of context an eager generator skips. Add a public git repository with the key in an early commit, and the leak now has a history that deleting a file doesn't erase.
Where to look in your own app
- The page source: open your live site, view source, and search for your providers' secret-key prefixes.
- The repository — including its history: a key removed in the latest commit is still present in every clone of an older one.
- Client-visible config: environment variables exposed to the frontend build end up readable by anyone; only values meant to be public belong there.
- Storage buckets and admin routes: not keys, but the same class of finding — things reachable without authentication that assume nobody will look.
Rotate, don't delete
The instinct on finding an exposed key is to remove it from the code. That treats the symptom. The key itself must be considered copied the moment it was public: generate a new one, revoke the old one, and only then clean up the code — this time keeping the secret server-side. Rotation is the only step that actually closes the door.
The boring principle behind all of it
Least privilege: every key as narrow as possible, stored in one controlled place, readable by as few systems as necessary. It's the same principle we apply to our own access to client systems — and it's checked, with evidence, in every Health Check.