GitGuardian counted 28,649,024 new hardcoded secrets in public GitHub commits in 2025. That is a 34 percent rise from 2024, the largest single-year jump in their series. Teams still treat GitHub secret scanning as if it made a public repository safe for credentials. It did not. It delayed a subset of partner-shaped tokens.
Push protection is a pattern match at the remote. Generic secrets, git history, gists, and a one-click bypass sit outside that match. Partner notification buys minutes for AWS and Stripe. It does not inventory what you already committed.
What GitHub actually blocks
Secret scanning on public repositories is free and automatic. GitHub documents the scope: git history on all branches, issues, pull requests, Discussions, wikis, and secret gists. Partner patterns get forwarded to the issuer. GitHub personal access tokens leaked in public repos are revoked by GitHub itself.
Push protection is the earlier check. It refuses a push that contains a detector GitHub has high confidence in. The June 2026 changelog added default push-protection for Cloudflare tokens, OpenRouter keys, Supabase PATs, and others. The list grows every few months. That is the product working as designed.
The list is also the limit. GitHub's pattern table splits detectors into partner, user-alert, push-protection-default, and configurable. Generic connection strings and home-grown API keys sit in the generic or custom buckets. Those are not the default push-protection set. GitGuardian's 2025 report, covering 2024, put generic credentials at 58 percent of detected leaks. A regex that only fires on Stripe and AWS will miss most of the volume.
Validity checks are a second product, not the same as partner notification. Partner notification tells Stripe or AWS that a public repo just received their token. Validity checks tell you whether a secret in your alert is still live. GitHub documents the split. Mix the two and the team waits for a vendor. The vendor never sees a custom API key.
The four holes that remain
The first hole is generic secrets. A DATABASE_URL with a password. A Postman PMAK- key that is not yet a default detector. A bearer token with no vendor prefix. Push protection does not block what it cannot name.
Code search still finds the leftovers. These queries are boring on purpose:
path:.env password
filename:.npmrc _authToken
"Authorization: Bearer" extension:md
filename:mcp.json env
None of those strings is a partner detector. All of them are how internal APIs, package registries, and agent configs actually ship credentials. GitHub will index the file. It will not refuse the push.
The second hole is history. Secret scanning will alert on an old commit. Push protection will not un-commit it. Rotation is the fix. Rewriting history is optional and often skipped. GitGuardian retested secrets first seen in 2022. 64 percent were still valid in January 2026.
The third hole is the bypass. A developer with write access can push through protection by giving a reason. Organizations can lock this down with delegated bypass. Most public repos never turn that lock on. The control then becomes a dialog, not a gate.
The fourth hole is the private-to-public flip. Push protection on private repos is a paid GitHub Secret Protection feature. Secrets committed while the repo was private become public the moment visibility changes. GitGuardian found internal repositories six times more likely to contain hardcoded secrets than public ones. The day you open-source the prototype, you publish the leftover keys.
AI commits doubled the leak rate
GitGuardian scanned public commits through 2025. Secret leak rates in AI-assisted code were roughly double the GitHub-wide baseline. Leaks tied to AI services rose 81 percent year over year, to 1,275,105. MCP server docs often tell people to put credentials in config files. The same report attributes more than 24,000 exposed secrets to that pattern.
GitHub is adding detectors after the fact. Lovable Labs joined the partner program in August 2026. GitGuardian detected 113,000 new DeepSeek API keys in 2025, before a detector existed. The gap between a new SaaS token format and a default push-protection rule is measured in months. Agents generate the config in seconds.
What a practitioner actually does
Turn on push protection and leave it on. That is table stakes, not a strategy. Then treat GitHub as one surface among several.
Scan for generic patterns, not only partner prefixes. gitleaks and trufflehog still catch connection strings GitHub will not block. Run them on history, not only HEAD.
Assume every public gist and every fork is in scope. GitHub scans secret gists. It does not make the gist private for you. A gist created to debug a webhook is still a public document with a guessable URL until you delete it.
Forks copy the blob. If the parent later rotates, the fork keeps the old value until someone force-pushes or deletes the repo. Secret scanning on the parent does not fan out a revoke to every fork. That is your job.
Rotate on alert. Do not wait for a rewrite of git history. The credential is the asset. The commit is the evidence.
If the work is a bounty or a vendor review, search what GitHub will not. Filename filters, .env remnants, Authorization: Bearer in examples, MCP json with env blocks. Related method on this site: GitHub OSINT and [five leak surfaces HIBP will not show](https://blog.mago.team/post/five-credential-leak-surfaces-hibp-wont-show).
mago.team runs that pass as a pipeline. The local encoding of the same idea is spy. Neither replaces rotation. Both keep the first hop honest.
GitHub's scanner is a good delay. It is not a boundary. Plan the inventory as if the delay failed, because for generic secrets it already did.
Top comments (0)