×

How to Find and Remove Leaked Secrets From Your GitHub Repositories in the US

How to Find and Remove Leaked Secrets From Your GitHub Repositories in the US

How to Find and Remove Leaked Secrets From Your GitHub Repositories in the US

A password that slips into a GitHub repository is public the moment the push lands, and deleting the file later does not take it back. Git keeps every earlier version, and forks keep their own copies. The good news is that finding these leaks is straightforward once you know where to look. This guide walks through searching your repositories, scanning your history, rotating what leaked, and cleaning up so it does not happen again.

Search your repositories for risky files

Start with the obvious places. Open GitHub and search your own account or organization for files that should never be public: `.env`, `settings.local.json`, `id_rsa`, `.pem` files, and anything named `credentials` or `secrets`. GitHub code search lets you narrow the search with qualifiers such as `filename:` and `org:`, so you can check one organization at a time. You need to be signed in to search private repositories, and only people with access to a private repository can see its contents.

Look beyond file names too. Search for text patterns such as `password =`, `api_key`, `BEGIN RSA PRIVATE KEY`, and `AKIA` for AWS keys. A hit does not always mean a live secret, but every hit deserves a look. Check your organization's `.gitignore` templates as well, and add entries for local settings files if any are missing.

Turn on GitHub's built-in protection

GitHub scans public repositories for known secret formats by default, and it raises an alert when it finds one. Open the Security tab on each repository and look at the secret scanning alerts. For private repositories, check that secret scanning is turned on in the repository settings under Code security. Alerts tell you which file and which line contain the secret, and they link to the partner's guidance on revoking it.

Push protection is the other half of the defense. When it is on, GitHub blocks a push that contains a secret in a known format and warns you before the secret ever reaches the remote. In most recent versions, push protection is turned on by default for public repositories. For private repositories, turn it on in the same Code security settings page. It costs nothing and it catches the exact mistake this guide is about.

Scan the code you already have

Built-in scanning only catches secrets in known formats, so run a dedicated scanner over your repositories as well. Two free open-source tools cover most cases. Gitleaks scans a folder or a whole git history for secrets and reports file names and line numbers. TruffleHog does the same and can also scan git history, files, and cloud storage. Both run from the command line, and both are free to download and use.

Run the scanner on a local clone of each repository, then run it again with history scanning turned on. A password typed inside a command, such as after `PGPASSWORD=` or `mysql -p`, can slip past both tools because it looks like an ordinary word rather than a formatted key. Treat any file the scanner flags as leaked until you prove otherwise.

Check git history, not just the current files

Deleting a secret from the current version of a file leaves every older version in git history. Search history with git log --all -p -S 'password' to find commits that added or removed a matching string, or use git log --all --full-history -- "*settings.local.json" to list every commit that touched a file. Scanners such as gitleaks and TruffleHog can scan history too, which is faster than reading log output by hand.

If history holds a secret, purging it means rewriting history with git filter-repo or BFG Repo-Cleaner. That changes commit hashes, so everyone working on the repository must re-clone it. Forks keep their own copies of history, so a purge of your repository does not clean a fork. Rotating the secret matters more than purging history, so rotate first either way.

Rotate first, then clean up

Order matters here. Before you delete anything, revoke or regenerate every secret that leaked. Change the password, create a new API key, and disable the old one. For cloud keys, create a replacement key, move your services to it, and then delete the old key. For a database password, set a new one and update every service that connects with it.

Only after the old secret stops working should you remove the file and purge history. If you clean up first and rotate later, the secret stays usable in the gap between the two steps. Keep a short list of everything the leaked file ever held, because a file edited over months may have held several different secrets. Rotate all of them, not just the one you spotted.

Keep it from happening again

Add the risky files to your repository's `.gitignore` before they are ever committed, and use GitHub's gitignore templates as a starting point. A `.gitignore` entry for `.env`, `.claude/settings.local.json`, and similar local files stops the accident at the source. Set up a pre-commit hook that runs a secret scanner before each commit, so a slip is caught on your own machine instead of on GitHub.

Store secrets in GitHub Secrets for your Actions workflows instead of pasting them into workflow files, and keep local secrets in a password manager or a secrets manager rather than in plain text files. Finally, make the check a habit. A quick scan of your repositories every few months catches the leaks that slip through on a busy week.

Frequently Asked Questions

Is deleting the leaked file enough to fix the problem?

No. Deleting the file only removes the current version. Older versions stay in git history, and forks of the repository keep their own copies. You must rotate the secret first so the leaked value stops working, then remove the file and purge history if you can.

Is GitHub secret scanning enough on its own?

No. GitHub secret scanning catches secrets in known formats, such as AWS keys and common API tokens, but it can miss a plain password typed inside a command. Run a dedicated scanner such as gitleaks or TruffleHog as well, and search manually for risky file names.

What if the secret is in a fork I do not control?

Rotate the secret right away, since that is the fix that works no matter who holds a copy. Then ask the fork owner to delete the fork or purge the file, and report the repository to GitHub if it contains credentials that put accounts at risk.

Post Comment