Hardcoded secrets end up in source code more often than most teams assume, and they are disproportionately common in AI-generated files: migration scripts, seed data, quickly scaffolded config, and test fixtures. Here is how to find every instance, including the ones that have already been “deleted.”
Check git history, not just the current branch
A secret committed once and removed in a later commit is still in every prior commit, retrievable by anyone with read access to the repo. Scanning only the working tree misses the most dangerous category: secrets that were “removed” but never rotated.
# Scan full git history with trufflehog
trufflehog git file://. --since-commit HEAD~50
# Or with gitleaks
gitleaks detect --source . --log-opts="--all"
# Quick manual check for common patterns
git log --all -p | grep -E "sk_live_|ghp_|AKIA|postgres://|mongodb+srv://"Scan your own app for issues like these
Paste your live URL. We check what your app serves publicly for exposed keys and misconfigurations. No account, no install.
Where AI-generated secrets actually hide
- Database migration and seed files. AI tools use real-looking credentials as test data, and those files ship to production.
- Config scaffolding. A real key gets used “temporarily” to get something working, then stays.
- Test fixtures and mock data. An AI tool reads from your
.envduring generation and reuses the real key in a test file. - Fallback values.
process.env.SECRET || 'hardcoded-default'— the default activates if the env var is ever missing. See fallback secrets. - Comments. An AI tool pastes an example value in a comment using a real key from context.
Scan patterns to look for
# Common prefixes by provider
sk_live_ → Stripe secret key
ghp_ → GitHub personal access token
AKIA → AWS access key
eyJ → Base64 JWT (check if it's a real service token)
postgres:// or postgresql:// → Database connection string
mongodb+srv:// → MongoDB Atlas connection string
xoxb- / xoxp- → Slack bot/user tokens
AIza → Google API key
# Also search for
grep -rn "passwords*=s*['"]" .
grep -rn "secrets*=s*['"]" .
grep -rn "api_keys*=s*['"]" .What to do when you find one
Rotate first. Deleting the line, rewriting git history, making the repo private — none of these steps invalidate the secret. An attacker who already found it still has it. Go to the provider, revoke or regenerate the key, and then clean up the code. A rotated key is safe even if it remains in history; an unrotated one is not safe even if history is clean.
After rotation: remove the secret from source, purge it from git history using git filter-repo or BFG, and move the new secret to a server-side environment variable. See how to remove a secret from git history and what happens when you push an API key to a public repo.
Make it impossible to merge again
Add a secret-scanning check to your CI pipeline so a hardcoded credential blocks the pull request before it reaches main. This turns a recurring manual search into an automatic gate. Prbl’s scanner runs on every PR and comments with findings before merge.
Common questions
How do I find hardcoded secrets in my code?
Start with a grep for common patterns: sk_live_, ghp_, eyJ (base64 JWT headers), postgres://, mongodb+srv://, AKIA (AWS keys). Then use a dedicated scanner like trufflehog or gitleaks that understands hundreds of secret formats. Run it against your full git history, not just the working tree, because a deleted file is still in every prior commit.
Does deleting the file remove the secret from git?
No. Deleting a file creates a new commit that removes it from the working tree, but every prior commit still contains it. Anyone with git clone access to the repo can check out those commits and read the secret. The only way to remove a secret from git history is to rewrite history with git filter-repo or BFG Repo-Cleaner. And even then, any fork or clone made before the rewrite may still have it.
What should I do when I find a hardcoded secret?
Rotate it first, before doing anything else. Deleting the line, removing the commit, or rewriting history does not invalidate the secret — an attacker who already found it still has it. Rotation at the provider is the only step that actually protects you. After rotating: remove the secret from source, purge it from git history, move the new secret to an environment variable, and scan for any other instances.
Where do hardcoded secrets hide in AI-generated code?
The most common locations are database migration and seed files (credentials used to set up test data that ship to production), config files with a 'temporary' hardcoded key, test fixtures that reuse a real key from .env, and fallback values in environment variable lookups (process.env.SECRET || 'hardcoded-default'). Also check git commit messages and PR descriptions — some AI tools paste key values into comments.
What is the best tool to scan for hardcoded secrets?
For git history: trufflehog (deep git history scan) and gitleaks (fast, configurable, good CI integration). For CI/pre-commit: gitleaks has good pre-commit hook support. For a no-install scan of a public URL, Prbl's exposed-secret-checker scans your deployed app's client-side bundles for keys that leaked to the browser. For a full repo scan including auth routes and JWT handling, Prbl's repo scanner covers both secrets and the code-level vulnerabilities that often accompany them.