Secretus logo
newscrowdsectanstacknpm

CrowdSec’s Own Breach: The Account Nobody Closed, and the Secrets That Weren’t There

A stolen OAuth token from a departed developer copied 170 private repositories. CrowdSec’s candid post-mortem shows what lingering access costs—and what scoped credentials save.

·8 min read·Secretus Editorial

He left on good terms. His GitHub access stayed open so he could finish some work. Three days later, 170 private repositories walked out through his account. CrowdSec published a detailed post-mortem on September 18 about an incident that began with a compromised npm package and ended with its source code on a public forum four months later. It is an unusually candid document from a security company describing its own failure, and it is worth reading for both halves of the story: the control that was missing, and the one that held.

What is confirmed

CrowdSec's timeline starts on May 11, 2026, when the TanStack npm packages were compromised. Installing an affected version ran code that stole credentials from the developer's machine—GitHub tokens, SSH keys and cloud credentials. One of the machines affected belonged to a CrowdSec developer who had recently left the company.

On May 22, between 05:52:29 and 06:01:33 UTC, that former employee's account downloaded approximately 170 private repositories using a stolen GitHub OAuth token. CrowdSec says the account was still active because “we parted on good terms with our developer, and he wanted to finalize some work.” It was removed on May 25 — three days after the copying.

Nothing surfaced for nearly four months. On September 16 at 17:45 an archive of the source code was published on a forum; CrowdSec was contacted about it at 20:00 the same evening, completed initial forensics and token rotation on September 17, and published its report on September 18. The archive timestamps matched May 22.

The repositories contained the SaaS console codebase, data science scripts and models, the consensus algorithm used for blocklist management, and automation scripts for deployment, QA and Slack bots. The leaked archive also exposed 83 user email addresses — which CrowdSec puts at roughly 0.05% of its user base, mostly monitoring accounts used by its data science team — along with the names, email addresses and investment context of 51 potential investors from 2020.

The half that worked

Here is the finding that deserves more attention than the breach itself. Across 170 private repositories belonging to a security company, CrowdSec reports that the only useful credential in the leak was a token for AWS SNS, and that it was properly scoped — live, but limited to publishing notifications to a single topic. Someone tried it on August 17, probing what it could reach, and got no further. Other tokens had already been rotated or could not be used from the internet.

That is what good secret hygiene looks like from the inside of an incident. The attacker got the code. They did not get the keys to anything, because the keys were not in the code, and the one that was had been scoped down to near-uselessness. Most organisations that lose 170 repositories have a much worse week than this.

What CrowdSec says it does not know

The post-mortem is honest about its limits. CrowdSec says it could not establish the origin of the compromise from package analysis or Git history, and that tracing the OAuth token through organisation audit logs was “a dead end” — no traces existed beyond its use. It does not claim to know who published the archive or why the gap between May and September was so long.

That audit-log gap is itself a lesson. A stolen OAuth token used by the legitimate account it belongs to does not look like an intrusion. It looks like the developer doing what the developer does.

Offboarding is a secrets problem

The proximate cause here is not exotic. Access was kept open past a departure as a courtesy, which is a decision every organisation makes and almost none records. The window was short by normal standards—the account was closed within weeks—and it was still long enough.

A practical offboarding checklist that actually addresses this:

  1. Make “finishing some work” a scoped exception, not an open door. If a departing person genuinely needs access, grant it to the specific repositories for a specific number of days, with an owner and an end date, rather than leaving the full account live.
  2. Revoke tokens, not just the account. OAuth grants, personal access tokens, SSH keys, deploy keys and app installations often survive independently of the human. Enumerate them explicitly at departure, and revoke them at the issuer.
  3. Treat the departing person's device as out of scope from day one. CrowdSec notes it did not enforce endpoint protection on developer machines at the time and has since deployed it. A machine you no longer manage is a machine whose credentials you should assume are exposed.
  4. Log and alert on bulk repository reads. One account cloning 170 repositories inside nine minutes is a detectable pattern, and one worth an alert regardless of who the account belongs to.
  5. Run the offboarding clock from the last working day, not from when someone remembers. Hours matter less than having the process complete at all.

Then check what is actually in your repositories

CrowdSec got a good answer to this question because they had done the work beforehand. You can find out what your own answer would be without waiting for an incident:

  • Scan history, not just the working tree. A credential deleted in a later commit is still in the clone. Removing it from the current files removes it from your view, not from the attacker's.
  • Scope every credential to the narrowest thing that works. The SNS token is the model: it was live, it was found, it was tried, and it still went nowhere. Scope is what converts a leak into an inconvenience.
  • Prefer short-lived tokens and workload identity over anything long-lived enough to be worth stealing four months later.
  • Assume a copy taken today may surface in September. Rotation schedules built around “nobody has reported anything” are built on the absence of evidence.

And the supply-chain link is worth stating plainly rather than dramatising: this chain started with a package install on a laptop. Lockfiles, install-script controls, and treating npm install as code execution by an untrusted third party are the upstream controls that would have shortened this story.

Where Secretus fits—and where it does not

Secretus can reduce plaintext exposure when an authorized person must hand over a small, temporary value—a replacement token after a rotation, a scoped credential for someone finishing a handover—through a channel that does not retain it the way chat and ticketing do. Handing a departing colleague a time-limited value is a better shape than leaving an account open.

It is not a secrets manager, not an identity provider, and not a way to keep credentials out of a repository. It cannot revoke an OAuth grant, cannot scan your Git history, and would not have detected the token use in this incident. The controls above are the substance; a one-time channel only helps with the handover step.

Sources