Secretus logo
newsgithubtruffle-securityleaked-credentials

543,699 Live Credentials in Public GitHub Repos: Push Protection Helps, Revocation Is What Matters

Truffle Security tested credentials found in 224 million public repositories and found more than half a million still working, a median of 784 days after exposure. The lesson is that deleting a commit is not the fix.

·8 min read·Secretus Editorial

The usual advice after a leaked key is to remove it from the repository. A new study suggests how little that achieves: the credentials that matter are the ones nobody revoked. Truffle Security, the company behind the TruffleHog scanner, reports that it found 543,699 unique credentials in public GitHub repositories that still authenticated when it tested them in July 2026. The median one had been sitting in a public default branch for 784 days.

These are Truffle's own figures, and we could not replicate them. They are still unusually specific about where the problem sits, and that makes them useful for deciding what to do on Monday.

What the study reports

Truffle says it scanned about 224.5 million repositories and 58.5 billion files from The Stack v3, a dataset assembled for AI training, from a crawl that closed on 7 August 2025. It then tested the credentials it found against their providers on 27 and 28 July 2026, counting a credential as valid only if it successfully authenticated. BleepingComputer reported the findings on 30 September.

  • Scale. 543,699 unique valid credentials, including copies in forks.
  • Age. A median exposure of 784 days. About 10% of the working credentials were more than 6.3 years old, and the oldest dated from 2009.
  • Types. Among the largest groups were Google Cloud service accounts (69,041), MongoDB connection strings (51,067), Google API keys (33,343), Postgres connection URIs (11,465) and SendGrid keys (9,189).
  • Trend. The density of working credentials rose from about 3.7 per million files in 2015 to about 11.6 in 2025.
  • Push protection. GitHub turned secret-scanning push protection on by default in February 2024. About 199,843 of the valid credentials, or 36.8%, were pushed after that. Truffle says the protection roughly halves the rate (a 53% drop in density) for the credential types it recognises, but 51.8% of the live credentials are shapes it does not cover, such as database connection strings and certain API keys.

What it does not show

  • Abuse. Truffle says it cannot tell how many of these credentials were actually stolen or used. A valid credential in public code is exposed, not proven compromised.
  • Today's state of GitHub. The crawl closed in August 2025, so some repositories may have changed since. What was tested in July 2026 was the credentials, not the live repositories.
  • Independent replication. The numbers come from one vendor with a commercial interest in secret scanning. Press coverage repeats them rather than reproducing them.
  • What is behind each credential. A valid database string tells you it authenticates, not what data it can reach or whether the database is reachable from the internet.

What it means in practice

Three points hold even if you discount the exact numbers.

First, detection at push time does not touch what is already out there. Truffle's own description is that the block has nothing to say about the hundreds of thousands of credentials already public. If your history contains a secret from before February 2024, push protection never saw it.

Second, the unprotected shapes are the ones that survive. Connection strings and generic API keys do not have a recognisable provider prefix, so they slip past default checks, and MongoDB connection strings were the second-largest group Truffle counted. A string that embeds a password is a credential whether or not a scanner has a name for it.

Third, deletion is not revocation. A commit that removes a key leaves it in history, in forks and in every clone and dataset that copied it. The only reliable fix is to make the credential stop working.

What to do

  1. Treat any secret that has ever been committed to a public repository as compromised. Rotate or revoke it first, and clean the history second.
  2. Scan the whole history, including forks you own and commits older than February 2024. Include custom rules for connection strings, private keys and generic tokens that default scanners skip.
  3. Prefer credentials that expire. Use workload identity or short-lived tokens in place of long-lived service account keys, and where your provider allows it, disable the creation of new static keys by policy.
  4. Make a leaked string less useful. Restrict databases to known networks, scope API keys to specific services and apply spending or usage limits, so a string found in the wild cannot be used from anywhere.
  5. Check that revocation actually works. Pick a test key, revoke it and confirm the provider rejects it. The study's central finding is that a lot of leaked credentials simply stayed alive.
  6. Give people somewhere else to put secrets. Developers commit credentials because passing them around is awkward, so a clear alternative removes much of the temptation.

The human handover that fills repositories

Many of these leaks begin as a convenience: a teammate needs the database string, so it goes into a config file, a README example or a pull request. Onboarding, contractor access and incident-response handovers all create the same moment. A one-time channel for that moment is cheap, and it keeps the value out of the chat, the ticket and the repository.

Where Secretus fits, and where it does not

Secretus handles the handover: a person encrypts a short text secret in the browser and shares a link that stops working after the expiry they chose or the first successful open, so the value is not left in a chat log or a file that later gets committed. Team Split can require several holders to reconstruct a high-value text secret.

It is not a secret scanner, a revocation tool or a secrets manager. It does not find credentials in your repositories, rotate them with providers, or make an application fetch short-lived credentials. Use scanners and your providers' tooling for that, and use a one-time link for the moment one person gives another a value.

Sources