Security Guides
543,699 credentials published on GitHub still worked (2026 study): why you must revoke, not delete, and what developers should do
A 2026 study found 543,699 credentials in public repos still worked. What the numbers mean, why deleting isn't enough, and what to do: revoke, check usage, replace.
Who this is for: developers who keep code in public repositories such as GitHub, and companies that run APIs. This article restates the numbers from a security company's study in this site's own words. It does not cover how to find other people's credentials.
What this study is (not an official GitHub study)
On 29 September 2026, Truffle Security, a security company that sells secret-scanning tools, published a study of credentials left in public repositories. As a vendor of detection tools, the publisher has a commercial interest in the topic. This article uses the study's numbers as reported and marks this site's interpretation separately.
GitHub did not leak anything. The credentials were written into code and published by the owners of each repository. GitHub's role is to provide prevention features such as push protection (blocking pushes that contain secrets), and as shown below, those features cover a limited set of types.
How the study worked, and how to read the numbers
- The source data is The Stack v3, a dataset of public repositories collected by a third party for training LLMs (large language models). Collection closed on 7 August 2025.
- Only the default branch (such as main) at collection time was examined. Older commits, other branches and anything removed earlier are not included. It is not a scan of all public code on GitHub.
- "Live" means the provider confirmed the credential still authenticated on 27-28 July 2026. Some may have been revoked since.
- The time since exposure is counted from the last modification date of the file containing the credential. The study notes this tends to understate the real age.
- Some types are left out of certain figures. Google API keys were only tested against Gemini, and private keys cannot be tested without the host they belong to, so neither is included in the per-type survival figures.
The numbers: what was left, and how much
In the week of 29 February 2024, GitHub began turning on push protection by default for pushes to public repositories for all users. According to the study, 199,843 (36.8%) of the 543,699 live credentials appeared after that date.
In addition, 51.8% of the live credentials were connection strings, Google API keys or private keys, types that push protection does not block by default. For the types that push protection does cover, the number of leaks per million files fell by about 53% when comparing the 12 months before and after the change. Types it does not cover fell by only about 7%. The study itself notes other factors may be mixed in, such as cloud providers pushing customers toward short-lived credentials during the same period.
How many survived, by type
The table below recalculates percentages from the counts the study published. "Found" is the number of credentials found on default branches; "Live" is how many of those still authenticated at test time.
| Type | Found | Live | Live share |
|---|---|---|---|
| npm tokens | 101,886 | 1 | 0.001% |
| Hugging Face tokens | 30,437 | 15 | 0.05% |
| GitHub tokens | 73,048 | 260 | 0.4% |
| Slack tokens | 8,903 | 198 | 2.2% |
| Stripe keys (including test-mode keys) | 124,132 | 4,493 | 3.6% |
| AWS access keys | 82,411 | 6,819 | 8.3% |
| Docker Hub tokens | 3,790 | 1,244 | 32.8% |
| SendGrid keys | 22,800 | 9,189 | 40.3% |
| Google Cloud service account keys | 126,963 | 69,041 | 54.4% |
| MySQL connection strings | 2,421 | 1,806 | 74.6% |
| PostgreSQL connection strings | 12,985 | 11,465 | 88.3% |
| MongoDB connection strings | Not counted | 51,067 | — |
The detector used for MongoDB only records strings it managed to connect with, so no share can be calculated and the type is left out of the survival figures. Only the live count is reported.
Why the types differ so much
The difference comes less from how easy the credentials are to find and more from whether anyone stops them after they are found. Within what we could confirm in each provider's official documentation, the picture is as follows.
The issuer stops them automatically
- GitHub tokens: GitHub documents that valid tokens pushed to a public repository or gist are revoked automatically
- npm tokens: since 2019, npm revokes valid tokens found via GitHub and emails the owner
- Hugging Face: an official mechanism lets anyone, not only the owner, invalidate a leaked token
Only you can stop them
- Database connection strings: there is no issuer; they work until you change the password
- Many API keys: what an issuer does after GitHub notifies it is up to the issuer
- Private keys for your own servers: only the owner knows where they are used
GitHub's secret scanning partner program notifies issuers about credentials found in public repositories. GitHub's documentation recommends treating any secret it reports as public and compromised, but leaves the implementation to the issuer. The issuer decides whether to revoke, reissue or contact the user.
The two cloud providers respond in ways that are not the same as full revocation.
- AWS: AWS attaches a managed policy called "AWSCompromisedKeyQuarantineV3" to an IAM user whose access key may have been exposed. It denies certain actions, such as launching instances or changing IAM, but does not delete the key. AWS asks customers not to remove the policy and to follow the instructions in the support case it opens.
- Google Cloud: since 16 June 2024, service account keys detected in places such as public repositories are disabled automatically by default. Organizations can opt out (
WAIT_FOR_ABUSE) with the organization policy constraintiam.serviceAccountKeyExposureResponse. The study still found more than half live; it does not explain why.
This site's view: deleting leaves copies elsewhere
The study itself used a dataset built in August 2025. If an owner deleted a file after that, the credential is still in the dataset. The same is true of forks, other people's clones, mirrors, and search or AI training data.
So treat "pushed to a public repository" as "leaked", and invalidate the credential on the issuer's side. Rewriting history is cleanup to stop further spread.
Your repository
Delete or rewrite history
Forks, clones, mirrors
On other people's machines
Datasets, archives
Copies as of collection time
Revoked by the issuer
Every copy stops working
If you find you leaked one
Revoke the key with the issuer
Check for use and charges
Issue a new key and replace it
Clean the history last
If you find someone else's key, don't test it
If you come across a credential in someone else's repository, do not check whether it works. Tell the owner or the issuer. For supported types in public GitHub repositories, GitHub notifies the issuer.
Preventing leaks
Push protection helps, but it is not enough on its own. As the numbers show, types it does not block by default pass straight through, and users can bypass a block by choosing a reason. Combine it with the following.
- Scan before you commit: stop secrets on your own machine before the push with a scanner such as gitleaks (see stop secrets before they commit with gitleaks).
- Scan the history of old repositories: push protection does nothing for commits made before it was turned on. Scan the full history of neglected and archived repositories at least once.
- Use short-lived credentials: GitHub Actions can connect to AWS or Google Cloud with OIDC (receiving a credential valid only for a short time on each run) instead of storing a long-lived key. Hugging Face offers the same approach.
- Narrow what each key can do: read-only, specific APIs only, source IP or referrer restrictions, and an expiry date. This limits what a leak can cost you.
- Keep databases off the internet: a leaked connection string is useless if it cannot be reached from outside. Database connection strings were the longest-lived type in the table.
The basics of keeping secrets out of code are in what's actually dangerous about .env and API keys, and secrets left on web servers are covered in auditing public directories.
For companies that run APIs
What separated the top of the table from the bottom was whether the issuer stops leaked keys automatically. As the party that protects your users' keys, consider:
- Joining GitHub's secret scanning partner program, and revoking valid keys and notifying users when you are notified
- Giving keys a distinctive prefix (for example, one that starts with your service name) so they are easy to detect
- Offering a channel or API through which anyone can report and invalidate a leaked key
- Making expiring keys and narrowly scoped keys the default
Sources (public record)
The numbers in this article come from the public sources below. We have not reproduced the study's text or charts; we used only its counts and reorganized them.
- Study by Truffle Security (a provider of secret-scanning tools), 29 September 2026 — trufflesecurity.com
- Coverage: BleepingComputer (30 September 2026) / SecurityWeek (1 October 2026) / GIGAZINE (2 October 2026, Japanese)
- GitHub: push protection on by default (GitHub Blog) / About push protection / Supported patterns / Partner program / Token expiration and revocation
- npm: npm Blog (18 June 2019)
- Hugging Face: User access tokens (revoking a leaked token)
- AWS: AWSCompromisedKeyQuarantineV3
- Google Cloud: Automatically disabling leaked service account keys (16 May 2024) / Best practices for managing service account keys
Read next
- Prevent: Stop secrets before they commit with gitleaks / Secret leak checker (paste to scan)
- Basics: What's actually dangerous about .env and API keys / What is a .env file
- What a leak can cost: AI-written code leaked an API key and ran up fraudulent charges
- Attacks that target developer credentials: Defending against supply-chain worms / The TanStack, Nx Console and GitHub compromise chain (May 2026)
- Narrow key permissions: SSH key least privilege
FAQ
QIs this an official GitHub study?
No. It was published on 29 September 2026 by Truffle Security, a security company that provides secret-scanning tools. GitHub did not leak anything: the credentials were written into code and published by the owners of each repository. GitHub provides prevention features such as push protection and secret scanning, but they cover a limited set of credential types.
QI committed an API key. Is deleting the file or rewriting history enough?
Once you push to a public repository, copies may already exist in forks, other people's clones, mirrors and datasets like the one used in this study. Deleting the file or rewriting history does not remove those copies. The first step is to revoke the key with its issuer and issue a new one. Clean the history afterwards.
QWon't the issuer revoke a leaked key automatically?
It depends on the issuer. GitHub's documentation says valid GitHub tokens pushed to a public repository are revoked automatically, and npm has done the same for its tokens since 2019. Under GitHub's secret scanning partner program, however, what an issuer does after being notified is left to the issuer. Credentials with no issuer behind them, such as database connection strings, are not stopped by anyone.
QDoes GitHub push protection prevent this?
Partly. By default, push protection blocks specific token formats listed in its supported patterns. GitHub's pattern list shows Google API keys and MongoDB and PostgreSQL connection strings as alert-only, without push protection. Users can also bypass a block by choosing a reason, or turn the feature off. Combine it with pre-commit scanning and short-lived credentials.
QWhat does "live" mean in the study?
The study matched credentials by pattern, then asked each provider whether the credential still authenticated on 27-28 July 2026. It did not check what permissions they had or whether they were abused. Some may have been revoked since.