543,000 Active Secrets Found in Public GitHub Repositories

Truffle Security analyzed 224 million public GitHub repositories and found 543,000 active secrets. Many had been exposed for years, while some go undetected by GitHub’s built-in push protection.

· 4 min read · 4 comments

On October 12, 2026, Truffle Security presented the results of its analysis of public GitHub repositories, as reported by Habr. Analysts examined 224 million repositories and 58 billion files, finding 543,000 tokens, keys, and passwords that were still in use. The study shows not just the scale of secrets being published in code, but how long they can remain publicly accessible.

Secrets Remain Exposed for Years

On average, the credentials found had been publicly accessible for 784 days. The oldest keys that were still active dated back to 2009. In other words, an old exposure does not necessarily become harmless over time: what matters is whether access through the exposed credentials has been revoked.

The share of active credentials varied widely by service. Of the 101,886 NPM tokens found, only one was active—about 0.001%. For GitHub, the figure was 260 out of 73,048 tokens, or 0.35%. Of the 30,437 Hugging Face tokens, 15 were active—roughly 0.05%.

Database connection credentials told a different story: 11,465 of the 12,985 PostgreSQL credentials were still active, or 88%. For MySQL, researchers reported a rate of 74%. For Google Cloud, 69,041 of the 126,963 credentials found were active—54%; for SendGrid, 9,189 of 22,800, or 40%; and for Docker Hub, 1,244 of 3,790, or 33%.

These differences matter when interpreting the results. A large number of tokens found does not, by itself, tell us how many are still active. Nor can the low share of active tokens for one service be applied to credentials for another: the researchers found a very different picture among exposed PostgreSQL connection credentials.

What Push Protection Missed

Around 200,000 credentials entered repositories after GitHub enabled push protection by default. It checks content during a push and can recognize tokens from several popular services, including GitHub, AWS, Slack, SendGrid, Stripe, and GCP.

Judging by the analysis, that is not enough to catch every exposed secret. Some credentials were in file formats the mechanism does not support, so the check did not detect them. The protection also has limits on the types of credentials it covers: it misses database connection details, Google API keys, and private keys.

For database connection details, the stated reason for this choice is to avoid false positives. That explains the limitation, but it does not change the consequences for a repository: exposed connection credentials can fall outside this automated check.

A successful push therefore tells you only that the mechanism did not block that particular push. It does not mean the files contain no secrets. The distinction is especially important for file formats the check does not cover or types of credentials it deliberately skips.

What This Means for Websites and Teams

The practical takeaway for a team maintaining a public repository is to scan it for secrets and find out whether any credentials they discover are still active. If access is still active, those credentials need to be replaced promptly. Removing a line from the current file and revoking an exposed secret are two different tasks.

A website owner does not need to know every type of token to ask the team a specific question: has the published code been checked, and what was done about any active credentials found? For developers, the study offers a guide to what to look for during that check: the exposed data may include not only service tokens but also database connection credentials.

My Take: A Successful Push Is No Reason to Relax

I’m writing my first TypeScript applications and learning how not to turn database work into an adventure, so the PostgreSQL figure struck me most. Of the connection credentials found, 88% were still active. For me, that is a good reason to look more carefully at my own code before publishing it and not assume that obvious tokens are the only things that might end up there.

I like the idea of stopping a mistake when changes are pushed: a warning at that stage is useful. But after seeing these figures, I would not treat the absence of a warning as the result of a thorough check. I would feel better searching the repository for secrets first, then checking whether any credentials I find are still active and replacing them if necessary. Automated blocking helps, but it will not build the habit of checking published code for me.

Sources

Where the news comes from. The text is a retelling in the author’s own words; the facts come from the source, the opinion is the author’s.

  1. Аналитики Truffle Security нашли в открытом доступе на GitHub 543 тыс. активных токенов, ключей и паролей habr.com

About the author

Lev Istrati

Junior full-stack developer

I’m writing my first apps in TypeScript and learning not to turn every database query into an adventure. Right now, I’m building a directory of local workshops to practice frontend and API development.

All posts by the author

Leave a comment

Not published. We’ll send a link to confirm your comment.

No links or ads. Your first comment is published after review. By sending a comment you agree to the privacy notice.

  1. The 784-day average is wild, especially with some active keys going back to 2009. I’m still learning how these scanners work—does the study say why GitHub’s push protection missed some of the active secrets, and what teams can add to catch them?

    1. The summary doesn’t give a specific breakdown of why push protection missed them, so I wouldn’t assume there was one single cause. Detection can depend on whether a token matches a recognized pattern; less obvious formats or credentials tucked into files and workflows may slip through. I’d treat push protection as one layer, then add secret scanning across the whole repo and history, plus a process to revoke and rotate anything exposed. The 2009 keys are a good reminder that deleting a secret from the latest commit isn’t the same as making it harmless.

    2. The summary doesn’t give a specific breakdown of why push protection missed them, so I wouldn’t assume it was one failure mode. A scanner can only catch patterns it recognizes; secrets in unsupported formats, unusual contexts, or older commits may slip through. Teams can add secret scanning in CI and across repository history, then make revocation and rotation part of the response—not just remove the value from the latest commit. The study’s active keys dating back to 2009 are a good reason to treat a successful push check as one layer, not a guarantee.

    3. Lev Istrati Post author

      The report points to a key limitation: push protection only checks what GitHub can recognize at push time, so secrets in unfamiliar formats or tokens that need extra context to identify can slip through. I’d pair it with secret scanning across the whole repo and history, plus provider-side rotation/revocation and alerts; a scanner finding a string is useful, but only the provider can tell you whether that credential still works. On my pet projects, I’ve also learned to keep credentials out of config files entirely and load them from environment variables. Does your team scan existing repos too, or mostly rely on checks before a push?