Truffle Security scanned 224.6 million public GitHub repositories — 58.5 billion files — taken from The Stack v3, the code corpus assembled to train large language models. On 27 and 28 July 2026 it tested what it found against the real services, and 543,699 credentials still authenticated.

They appeared 1.1 million times in total, because a leaked key in a forked repository is leaked again in every fork.

The numbers that describe the delay

The crawl behind the dataset closed on 7 August 2025. The validation happened eleven months later, and the credentials were still working.

The median one had been sitting in a public default branch for 784 days. The ninetieth percentile was 6.3 years. A quarter of the findings predate 2022. The oldest still-working credential was last modified on 13 June 2009 — database credentials in an Erlang configuration file, live for seventeen years.

That is not a story about anyone failing to notice a breach. Nobody breached anything. The credentials were published, in public, by their owners, and then nothing happened for years.

Push protection works, and it is not the thing that matters

GitHub turned on push protection by default on 29 February 2024, which blocks a commit containing a credential shape it recognises from more than 180 providers.

It works. Truffle's figures put the reduction in new credential commits at roughly 53 percent for the patterns it covers.

And it is not where the outcome is decided, for two reasons.

The first is arithmetic: 199,843 of the live credentials — 36.8 percent — were committed after push protection went on by default, and were still valid more than two years later. Protection at push time does nothing for what is already public, and does nothing for a repository whose owner turned it off.

The second is coverage: 51.8 percent of every live credential in the corpus is a shape that a default-configured public repository will accept without complaint. Among those are 51,067 live MongoDB connection strings and 33,343 live Google API keys. A connection string is not a token with a recognisable prefix. It is a URL, and it looks like every other URL.

The table that settles it

The comparison that makes this research worth reading is what happens to the same exposure under different providers.

CredentialCommittedStill liveSurvival
npm tokens101,88610.001%
GitHub tokens73,0482600.36%
Google Cloud service accounts126,96369,04154%
MySQL connection strings2,4211,80675%
Postgres connection strings12,98511,46588%

npm had more than a hundred thousand tokens published to public GitHub. One of them still works.

Nothing about npm's users is more careful than Postgres users. The difference is downstream: npm, GitHub and Slack operate scanning partnerships that take a leaked token and revoke it without asking. A Postgres connection string has nobody to tell. There is no central authority that owns it, no pipeline that can invalidate it, and the only person who can turn it off is the person who already published it by accident and did not notice.

Truffle's conclusion is the one the table forces: what keeps a leaked credential alive is the absence of revocation, not the absence of a block at push time.

The dataset is the second problem

Where this corpus came from matters as much as what is in it.

The Stack v3 exists to train models. These 543,699 credentials were not merely public — they were training data, read by every model built on that corpus, in a form the model may reproduce when asked for an example configuration.

That changes the shape of the exposure. A secret in a public repository is findable by someone who searches for it. A secret in training data is reachable by someone who asks a model to write a connection string and gets a real one. We have written before about an agent whose indicator list included an AI config file; this is the same collision from the other direction.

What to do

  • Rotate first, delete second. Removing the file does not help: the credential is in the fork, in the archive, and in the training set. Only invalidating it at the provider ends the exposure.
  • Audit what cannot be auto-revoked. Database connection strings, internal service URLs with embedded passwords and self-hosted API keys are the shapes with no revocation pipeline behind them, and they are where the survival rates are worst.
  • Do not treat push protection as the control. It halves new leaks of recognised shapes and does nothing for the half of this corpus it does not recognise.
  • Scan history, not just the current tree. A quarter of these findings predate 2022, which means the file in your working directory today says nothing about what is in your commit log.
  • If you publish a service with API keys, build the revocation pipeline. The npm column is what that is worth.

What is not established

  • Who, if anyone, has used these credentials. Truffle validated that they authenticate; it does not report abuse.
  • Whether the owners have been notified, and by whom.
  • How many of the 543,699 remain live now, after publication.
  • How much of this corpus is reproduced by the models trained on it, which the research does not test.