API Key Leaks on GitHub: What the Data Shows
Every year, tens of millions of secrets land on GitHub. They come from beginner mistakes, rushed commits, AI assistants, and CI misconfigurations. Here is what the data actually shows about how keys leak, how fast they are exploited, and what makes the problem worse than most developers think.
The scale of the problem
GitGuardian's annual State of Secrets Sprawl report is one of the most comprehensive public datasets on credential leakage. The 2025 edition, covering 2024, counted about 23.8 million new secrets in public GitHub commits, up from about 12.8 million the year before.
The count covers public commits only, so it says nothing about private repositories, internal CI logs or chat tools, where secrets also end up.
Commonly leaked credential types include generic API keys and passwords, cloud credentials (AWS, Google Cloud), AI provider keys, GitHub tokens and payment keys such as Stripe's.
How API keys end up on GitHub
The majority of leaks are not caused by deliberate carelessness. They fall into five patterns:
The forgotten .env file
A developer creates a .env file for local development, adds it to the repo before adding .gitignore, and the commit history permanently contains the secret. Even after deleting the file in a later commit, the key is in git history and can be recovered with git log.
The hardcoded quick test
A developer pastes a real key to test something quickly, intending to remove it. The commit is pushed before the cleanup.
CI/CD log exposure
A deployment script echoes environment variables for debugging. The CI log is set to public (common in open-source projects on GitHub Actions). Every variable is visible to anyone who views the run.
AI coding assistant autocomplete
The developer has a key in their clipboard or open in another window. The AI assistant autocompletes a code block using a value that resembles the format of an API key. The developer accepts the suggestion without reviewing it.
Dependency or template exposure
A project template, Dockerfile, or third-party package has a placeholder that resembles a real key format. A developer replaces the placeholder with their real key and commits. The key is then in a widely-forked or frequently-cloned repository.
The exploit window
Researchers who plant decoy keys in public repositories consistently report them being found and tried within minutes. That's because the attackers are automated: scrapers continuously monitor the GitHub public event API (the same API that powers GitHub's own notifications). When a commit is pushed, the bot downloads the diff, runs regex against it, and attempts to use any matched credential within seconds. The bot does not care if the commit is immediately reverted. Reverting a commit does not remove the key from git history, and the bot already has a copy.
The revoke-and-rotate timeline
The important observation here is that detection-and-response alone is too slow: the attacker's side is automated and the response involves people. The controls that change the outcome are pre-exposure (preventing the key from being committed) and exposure-tolerance (making a leaked credential worth as little as possible).
Git history is permanent - almost
GitGuardian's 2025 report found that about 70% of the secrets it detected leaking in 2022 were still valid. Many developers never learn their key leaked, or believe that deleting the file and pushing a new commit is enough. It is not.
Deleting a file in a git commit only removes it from the working tree. The file still exists in every prior commit. Anyone who clones the repository and runs git log -p can see every version of every file, including the deleted one with the key.
Proper removal requires rewriting git history with git filter-repo (the modern replacement for git filter-branch) and force-pushing. Even then, GitHub caches content via its API, and any fork or clone taken before the rewrite still contains the secret. For any key that was ever in a public repo - even briefly - treat it as permanently compromised and rotate immediately.
# Install git-filter-repo
pip install git-filter-repo
# Remove a specific file from all history
git filter-repo --path .env --invert-paths
# Force push (coordinate with your team first)
git push origin --force --all
# IMPORTANT: Rotate the key regardless.
# History rewriting is not a substitute for rotation.Why AI coding tools make this worse
GitGuardian's 2025 report found that public repositories with GitHub Copilot enabled leaked secrets more often than public repositories overall (about 6.4% versus 4.6%). That's a correlation, and the mechanism isn't fully understood, but several factors are likely contributors:
- ▸AI assistants autocomplete credential placeholders using values from context - clipboard, open files, or recently pasted content. Developers accept suggestions without auditing every line.
- ▸AI-assisted commits tend to be larger (more files, more context) - larger commits are harder for the developer to review before pushing.
- ▸AI tools sometimes generate boilerplate with hardcoded example values that look like real keys but use formats identical to live credentials.
- ▸Developers using AI tools often move faster and skip manual review steps, reducing the likelihood of catching a committed secret before push.
The practical implication: if your team uses AI coding tools, pre-commit scanning is more important, not less. A Gitleaks pre-commit hook is fast and catches common credential patterns before they leave the developer's machine.
What the data means for your security posture
The takeaway is that detection-and-response, on its own, loses the race for leaked credentials: automated abuse can start before a person can respond.
The two strategies that actually work are:
Strategy 1: Prevention
Pre-commit scanning (Gitleaks), .gitignore discipline, mandatory code review, no keys in CI logs. Prevents the vast majority of accidental leaks. Requires ongoing team discipline - the protection degrades when developers are under time pressure.
Strategy 2: Exposure tolerance
Design your credential architecture so that the thing that leaks is not the real secret - it is a host-bound token the proxy refuses from origins you haven't allowed. A scraper testing it from its own servers gets nothing. Pair it with rate limits and cost caps for the cases host-binding can't cover, such as forged headers from a server.
Prevention and exposure tolerance are complementary, not alternatives. Prevention reduces the attack surface; exposure tolerance limits the damage when prevention fails.
Make the next leak cheaper
KeyVault Edge implements exposure tolerance: your real key is encrypted with AES-256-GCM inside a signed token, and the edge proxy only exchanges it for requests from origins you allow.
Get started