To remove API keys and passwords from old code properly, do two things in this order: first revoke or rotate every secret that was ever committed, then rewrite the git history so the old values are gone from every commit, not only from the latest one. Deleting a file and committing is not enough, because the file is still sitting in the history. You can plan all of this before any code changes hands, and nobody needs to see your code to help you plan it.
Why do old repositories almost always contain secrets?
Because secrets were convenient at the time. A secret is any value that grants access: an API key, a database password, a cloud access token, a signing certificate, a webhook URL with a token in it. During development, people paste them into config files, test scripts and environment files such as .env, and some of those end up committed.
The scale is large. GitGuardian’s State of Secrets Sprawl 2026 found 28,649,024 new secrets in public GitHub commits in 2025, about 29 million, up 34% in a year. Private repositories are worse: 32.2% of internal repositories contained at least one secret, against 5.6% of public ones, so company repos were about six times more likely to hold hardcoded secrets. If your old product lived in a private repo, assume there is something in it.
Where do secrets usually hide in old code?
Look in these places first:
- Environment and config files: .env, .env.local, config.yml, settings.py, appsettings.json, application.properties, wp-config.php.
- Infrastructure files: Terraform state, Docker Compose files, Kubernetes manifests, CI pipeline files.
- Mobile apps: Firebase config files, signing keystores, hard-coded API keys in constants files.
- Scripts and notebooks: deploy scripts, data import scripts, Jupyter notebooks with output cells.
- Docs, READMEs, wikis and tickets: “to test, use this key” lines are surprisingly common, and ticket exports can carry pasted credentials too.
- Tool configs: files for AI coding assistants and MCP servers. GitGuardian’s 2026 press release says leaked AI service keys rose 81% in 2025, and MCP configuration files exposed 24,008 unique secrets.
Secrets also leak outside code. GitGuardian says about 28% of incidents start in collaboration and productivity tools, which is one reason we never take chat logs.
Why is deleting the file not enough?
Because git keeps everything. Every commit is a full snapshot, so a key committed in 2019 and deleted in 2020 is still in the 2019 commit. GitHub’s documentation is direct: if a deleted file contained sensitive data, “the data will still be available in the repository’s Git history,” and to remove it completely “you must remove the file from your repository’s history.”
That is why git history is both valuable and risky. The history is one of the things that makes old code worth more, as our guide on why git history adds value explains, so the goal is to clean it, not throw it away.
Why do you rotate secrets first?
Because rotating makes the secret useless, and nothing else does. GitHub’s guide on removing sensitive data says “as a first step you need to revoke and/or rotate that secret,” and notes that once a secret is rotated, rewriting history may not even be necessary for security.
This matters because old secrets often still work. GitGuardian found that 64% of valid secrets leaked in 2022 were still not revoked in 2026. A shut-down product may still have a live cloud account, a payment provider account or an email service key attached to someone’s card. While you rotate, look at each provider’s usage or access logs for activity you do not recognize. If a committed password was also used anywhere else, as personal passwords often are, change it there too. For secrets you cannot rotate, such as an old signing key, revoke or retire them and note it.
Rotating does not replace cleaning for a sale. The copy you hand over should not contain secrets at all, live or dead.
| Step | What it achieves | What it does not achieve |
|---|---|---|
| Delete the file and commit | Hides it from the latest version | Old commits still contain it |
| Rotate or revoke the secret | Makes the leaked value useless | The old value is still visible in history |
| Rewrite history with git-filter-repo | Removes the value from your copy of the history | Old clones, forks and cached views may still hold it |
| Rotate, then rewrite | Value is dead and gone from the copy you transfer | Nothing important left over |
How do you scrub secrets from git history?
The recommended tool is git-filter-repo. Git’s own documentation says the older filter-branch command “is not recommended” and points to git filter-repo instead. GitHub’s guide says to “rewrite the repository locally, using git-filter-repo,” with a version that has the --sensitive-data-removal flag, meaning at least version 2.47.
You do not need to type commands to follow the logic. The process is:
- Make a list. Write down every secret you found and every file that held one.
- Rotate or revoke each one in the service where it was issued, or confirm the account is closed.
- Work on a fresh copy. Make a new clone so your original backup stays untouched, and keep that backup offline or encrypted, because it still holds every secret.
- Rewrite history with git-filter-repo, removing whole files such as .env, or replacing specific values with a placeholder such as REMOVED.
- Check the result by searching the rewritten history, on every branch and tag, for each value on your list.
- Keep the clean copy as the one that will be transferred.
If you are not a developer, this is a good job for a former team member you trust. With us, this cleaning step happens after the written agreement is signed and before transfer, and we help with it.
What about forks, clones and old copies?
A rewrite cleans one copy. GitHub’s documentation warns that the commits “may still be accessible elsewhere”: in other people’s clones, in forks, in cached views reachable by commit hash, and through pull requests that reference them. Clearing cached views requires contacting GitHub Support, and a rewrite needs everyone with a copy to cooperate, because “one merge commit could reintroduce some or all of the tainted history.”
For a closed product with no active team, this is simpler than it sounds: there is usually nobody still pushing. Rotation is your real protection against the copies you cannot reach.
What should you never do while cleaning?
Two rules keep you safe. First, never run a script or tool sent by a stranger on a machine that holds your code or credentials. Download well-known open-source tools yourself from their official project pages. Second, a fair buyer does not need your code before a contract, and does not need you to install or run anything. If someone asks for either, read our list of red flags when someone offers to buy your code.
Secrets are only half of the cleaning job. The other half is customer data, covered in our guide to personal data in old code, and both fit into the wider checklist for preparing a codebase for sale.
What to do next
- Search your repository and its full history (every branch and tag, not just the latest files) for .env files, config files and words like key, secret, token and password; well-known open-source scanners such as Gitleaks or TruffleHog, downloaded from their official project pages, can help. Make a list.
- Rotate or revoke every secret on the list, or confirm the account behind it is closed.
- Then send us a few details for a free code valuation; no code is needed to start, and we help with cleaning after the agreement is signed.
Frequently asked questions
If I delete the .env file and commit, is the secret gone?
No. Deleting a file in a new commit removes it from the latest version only. Every earlier commit still contains it, and anyone with a copy of the repository can read it there. GitHub's own documentation says the data remains available in the repository's git history. To remove it properly, rotate the secret and then rewrite the history with a tool such as git-filter-repo.
Do I still need to rotate keys if the product is shut down?
Yes, if the account behind the key still exists. Many old keys still work years later: GitGuardian found that 64% of valid secrets leaked in 2022 were still not revoked in 2026. If the service account is closed, the key is dead, but check rather than assume. Rotating or revoking is the one step that makes a leaked secret harmless.
Do I have to clean the code myself before talking to a buyer?
No. You can start the conversation with no code at all. With us, secrets, keys and personal data are removed before transfer, after the written agreement is signed, and we help with that step. What helps early is knowing roughly where secrets might be, so the cleaning plan is clear. We never ask anyone to install or run anything on their computer.
Is it safe to run a secret scanner someone sends me?
Do not run a script or tool sent by a stranger on a machine that holds your code or credentials. Use well-known open-source tools you download yourself from their official project pages, or ask a developer you trust. A fair buyer does not need you to run anything for them, and does not need your code before a contract.
Find out what your old code is worth right now.
Tell us about the product in about a minute. No code needed. We review the details and come back with a cash offer or a plain no.
Get my free code valuation →