Secrets in Source Control: How Keys Leak, How They Are Found, and What Rotation Really Costs
When a secret is leaked in source control, the typical response is to remove the visible commit. But for GitHub users, that is not enough: it also means rotating all…

What’s in this piece
When a secret is leaked in source control, the typical response is to remove the visible commit. But for GitHub users, that is not enough: it also means rotating all dependent credentials immediately, wherever they were used. There is no way to reset a credential’s exposure after the leak have reached the repository, even if its source is erased.
The leak survives the commit
Enterprises face an ongoing risk from leaked secrets because a credential remains vulnerable after its source commit is removed. GitHub's secret scanning takes place after every code push, and inspects the entire history of the repository and all its branches. [When it finds a leaked API key, password, token, or other known secret type, it alerts the repository owner with the affected credential's details.][1]
If you receive a secret scanning alert, immediately rotate the affected credential to prevent unauthorized access that can occur.
There are two aspects to GitHub's secret detection: - Secret scanning identifies exposed credentials in the repository and alerts the owner, even after the vulnerable commit is removed. - Push protection blocks the push if a detected credential is added. With push protection, you would need to remove the added credential from the push.
Trying to stop the leak before it lands
In addition to secret scanning, GitHub also uses push protection to prevent future credential leaks. Push protection checks for high-confidence secrets being pushed to the repository and blocks the push if a secret is detected. It is enabled by default for all pushes to all public repositories, and free for all public repositories.
GitHub says push protection can detect and block secrets in: - Commits made in the GitHub UI that contain an exposed secret - Pushes from the command line that contain an exposed secret - File uploads to a repository that contain an exposed secret [5] - Requests made to the REST API [6] - Interactions with the GitHub MCP server [7]
However, push protection does not detect all secret types that secret scanning does. Some secret patterns require the credential pair, like an Amazon Web Services (AWS) access key and secret, to be in the same file. Secret scanning is a post-exposure mitigation, but push protection is a preventative measure.
Even after removing a secret from commit history, you may face some pain:
-
To ignore the rewritten history in a fork, the downstream repository owner would need to repush the fork after removing the history. Your action can block forks downstream.
-
You say that pull requests can proceed. But if the secret is in a branch with a pulled change, the change cannot be merged after it has failed review. The secret must first be removed from the relevant commits.[8]
What the scanner can and cannot see
While secret scanning detects most secret types, it has some scope limitations, according to the documentation. It can detect secret patterns in: - File contents
- Email body contents
- Directories and directory paths, when a new directory is added to the repository
-
Some filtered topics in pull requests and Issue templates
-
Dockerfiles, Docker Compose files, and some files in Docker multi-stage builds
However, it has some detection scope limitations: - It does not detect secrets in encrypted files, or secrets that are protected by use-restrictions, such as with GitHub Actions secrets. - It does not always detect secrets in: + Emoticons, such as:key: + Incorrect Markdown, such as wrapping the secret in brackets
+ File names, such as `secret.php`
[9] - Secret scanning settings can configure some secret patterns as push-protected by default, but not all. [10]
Why “rotation” is the real response
When a secret is detected, GitHub advises alert recipients to rotate the credential immediately to avoid unauthorized access. But rotation may not end with changing the credential value in the systems it touches. In some cases, rotation can also require: - Updating credentials in environment variables and CI/CD configuration - Changing the password for any cloud accounts, services, or integrations tied to the credential - Updating the credential used in mobile app, to check for credentials used at different times.
The time and complexity of credential rotation can be significant. When asked about key rotation, a source said, "The cost of rotation isn't just time; it's service disruption, too. We had to roll out new credentials in a coordinated way over several hours, which led to some down time as we swapped out the old for the new. A cred leak is like a ripple - it gets big."
The operational consequence
Credential leaks make any exposed service vulnerable, and they cost you money and time to mitigate. The leak is just the start: cred rotation is where a secret leak gets costlier. Unfortunately this article is focussed on the steps up to severity:
So while blocking a credential push or removing it from history can prevent future exposure, you still need to rotate the credential to prevent any access that already took place. Removing an exposed credential in a pull request can prevent unauthorized access, but may not stop it from happening. Pull requests are not exposed to the public, but they are shared with reviewers, and a reviewer with access to the credential could access it during review. Therefore, GitHub recommends rotating the credential immediately after it is detected, regardless of whether it was in a pull request, commit history, or other location.
Only after removing the secret from commit history can you re-push the commit, or retry a blocked push. A blocked push can be retried within three hours after following the provided URL and completing the allowed remediation or bypass flow. However, the exposed credential may still be available in code that has been forked or cloned from the repository. Therefore, rotating the credential immediately is the only way to fully mitigate the risk of exposure.
GitHub's secret scanning and push protection are powerful tools for detecting and preventing credential leaks. However, it is important to understand that these tools do not eliminate the risk of exposure entirely. Removing an exposed credential from commit history is necessary, but not sufficient. Rotating the credential is the only way to fully mitigate the risk of unauthorized access.
- 01Security & Privacy
What are dynamic proxies, and are they worth using?
Dynamic proxy servers are a key part of network infrastructure, playing an essential role in ensuring network traffic security, efficiency, and privacy. But what…
- 02Security & Privacy
Privacy by Design in Gambling Apps: A Practical Guide
The email starts like this: “We’re sorry to tell you there was a data breach. Your ID, bank info, and bet history may be exposed.” No team wants to send that note.…
- 03Security & Privacy
KYC and Age Verification Technologies: Balancing Compliance and UX
Your user is almost there. Card is ready. Then the app asks for a selfie and an ID scan. The light is bad. The timer is strict. The user quits. This scene plays out…
- 04Security & Privacy
Responsible Gambling Tools: Tech-Driven Safeguards and Self‑Exclusion
Sunday. Late. One more spin. Then two. You tell yourself you will stop at midnight. Your screen says you can add funds in a tap. Your pulse says “go.” Your plan…