Scanverra

How to Fix Hardcoded Secrets in Your Codebase

An API key, database password, or signing secret committed to a repository is compromised the moment it's pushed - not when someone finds it. Automated scanners crawl public (and leaked private) repos for exactly this pattern continuously.

What This Actually Looks Like

The pattern that gets flagged every timetypescript
1// Don't do this
2const STRIPE_SECRET_KEY = "sk_live_51H8x...";
3const DB_PASSWORD = "prod-p@ssw0rd-2024";

It doesn't have to be this obvious - secrets end up committed inside test fixtures, example config files copied from a real one, CI YAML files, or even code comments left in during debugging.

The Moment You Find One: Rotate First

  • Revoke and reissue the credential immediately, at the source (Stripe dashboard, database, cloud provider IAM) - before doing anything else. Assume it's already compromised.
  • Then remove it from history, since a rotated-but-still-visible secret is a much lower priority once it no longer works, but should still be purged.

Purging It From Git History

git filter-repo removes a file's content from every commit, not just the latesttypescript
1git filter-repo --path config.ts --invert-paths
2# then force-push the rewritten history and have all collaborators re-clone

Deleting the file in a new commit does not remove it from history - anyone can still retrieve it with git log -p or by checking out an earlier commit. Only rewriting history removes it, and that requires every collaborator to re-clone or hard-reset, so coordinate it deliberately.

Preventing the Next One

Move secrets to environment variables

Read from the environment instead of a literaltypescript
1const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;

Add a pre-commit secret scanner

Tools like gitleaks or detect-secrets can run as a pre-commit hook, blocking a commit before a secret-shaped string ever reaches your history in the first place.

Never commit real values in example/template config files

Use clearly-fake placeholder values (sk_live_xxxxxxxx) in any .env.example or sample config committed to the repo.

How Scanverra Detects This

Scanverra's repo scanner scans your full file tree for secret-shaped patterns - API key formats, private keys, connection strings, common vendor token prefixes - and flags each match with its location, as part of the same scan that also checks dependencies, code quality, and SAST findings.

FAQ

Frequently asked questions

Is a secret in a private repo actually at risk?

Yes - private doesn't mean inaccessible. Anyone with repo access (including former employees, contractors, or a compromised account) can see full commit history, and a private repo can be accidentally made public, forked, or included in a data export at any point.

If I delete the file with the secret in a new commit, is it gone?

No - it's still sitting in every earlier commit's history, retrievable with git log or git show even after the file is deleted or edited in a later commit. Removing a secret from history requires rewriting history (git filter-repo or the BFG Repo-Cleaner), not just committing a fix.

What should I actually do the moment I find a committed secret?

Rotate it first - assume it's compromised the second it was pushed, regardless of whether you can prove anyone accessed it. Only after the old credential is revoked and a new one is issued does purging it from history matter for anything beyond hygiene.

How do I stop this from happening again?

Add a pre-commit hook or CI check that scans staged changes for secret-shaped strings before they're ever pushed, and move configuration into environment variables or a secrets manager instead of inline constants from the start.

Free - no sign-up required

Scan your repo for exposed secrets

Run a free repo scan and find hardcoded credentials before an automated scraper does.

Run free audit