170 private CrowdSec repos cloned with a stale TanStack token
On September 16, 2026, a CrowdSec engineer opened a link to a cybercrime forum and saw the company's own private source code pasted in plaintext. The archive held the SaaS console, the AWS automation, the data-science models behind the malicious-IP blocklist consensus, and inside one .git/config file, a GitHub OAuth token beginning with gho_. The theft had happened four months earlier. Two days later, CrowdSec traced the credential back to a former employee whose laptop was compromised in the TanStack npm attack of May 11 (CrowdSec statement).
The four months between the theft and the disclosure
The threat group TeamPCP (also tracked as UNC6780) published 84 malicious versions across 42 @tanstack/* packages on May 11, 2026, between 19:20 and 19:26 UTC. A StepSecurity researcher flagged them inside half an hour, and the tarballs were pulled shortly after (StepSecurity postmortem).
Inside that window, one CrowdSec engineer installed an affected release on his personal laptop. The postinstall ran a credential harvester that pulled his GitHub OAuth token along with SSH keys and cloud material. Eleven days later, on May 22 between 05:52 and 06:01 UTC, an IP in Toronto used that token to clone about 170 private repositories from CrowdSec's GitHub organization (CVE-2026-45321).
The engineer had already given notice. His account was removed on May 25, three days after the clone. Nothing looked wrong on CrowdSec's side, because a departing developer running git fetch is the least anomalous thing in a working software org. Four months of silence followed, then a forum thread on September 16. GitHub support pulled the token's OAuth history, confirmed the read activity from that IP, and CrowdSec published its write-up on September 18 (CrowdSec analysis).
How a package install turned into a private repo dump
The TanStack compromise is a small masterpiece of workflow abuse. TeamPCP forked TanStack/router, opened a pull request, and hit the pull_request_target trigger on the release workflow. That trigger runs with the base repository's secrets while checking out the fork code. Combined with GitHub Actions cache scoping (writes are per repository, not per branch, and no permissions block gates the cache save), the fork job wrote a poisoned pnpm store into the shared cache namespace the release workflow later reads from.
When the next maintainer PR landed on main, the release workflow restored the poisoned cache, ran the attacker's binaries, and read the runner's OIDC token from process memory before the trusted publish call. The 84 tarballs went out under TanStack's real SLSA Build Level 3 provenance, the first npm worm on record to ship malicious packages with valid signed attestations (TanStack postmortem).
Once installed, the payload swept the standard paths for GitHub tokens, SSH keys, AWS, GCP, and Azure credential files, Kubernetes contexts, Vault tokens, and .npmrc entries, then exfiltrated through an encrypted messaging channel (Snyk analysis). It also planted a persistence trick: a background script polled the GitHub token every 60 seconds and, on any revocation, ran rm -rf ~/ against the home directory.
For CrowdSec, one of the exfiltrated tokens was the OAuth credential that let the attacker clone 170 private repositories eleven days later. No new vulnerability was chained; the token still worked because the engineer still had his access, and that access outlived the alarm window on the packages by a factor of ten.
Why CVE-2026-45321 sat outside every scanner's field of view
A CVSS first queue looks at CVE-2026-45321 (9.6 critical, active exploitation confirmed) and asks whether any of the compromised @tanstack/* versions appear in a production lockfile. When the answer is no, the finding closes.
The compromise does not live in production lockfiles. It lives on the developer laptops and CI runners that ran pnpm install or npm install against any project that resolved to a compromised version during the six minute publish window, or afterward through a stale cache. The exposure is a set of stolen developer credentials, and the blast radius is whatever they reach next day, next week, or next quarter.
A stolen credential is not tied to the machine that lost it. It works from Toronto, from a Tor exit, or from a residential proxy, and keeps working until it is revoked or expires. CrowdSec's token stayed live long enough to clone 170 repositories in nine minutes, and no one noticed for four months. The exposure the CVE describes and the exposure that costs the company are two objects on two clocks.
TRIS reads this as four exposure layers on different clocks
TRIS, the Threat and Risk Intelligence Scoring engine inside CVEasy AI, does not score CVE-2026-45321 as one number against one asset. It scores the finding across the layers where the compromise lives, and lets each layer settle on its own decay curve.
Package inventory layer. Does any lockfile reference a compromised @tanstack version? Even confirmed exposure here scores mid band, because the fixed versions are known and the malicious tarballs are gone from the registry.
Developer identity layer. Did a laptop, a CI runner, or a dev container install or transitively resolve to a compromised version in the affected window? On an exposed instance where the developer machine reached GitHub, npm, or a cloud console with the credentials it had cached, this layer lands in the top ACT band. On a sandboxed ephemeral runner with short-lived OIDC credentials, the same finding drops a band, because the primitive was present but the exposure that turns it into an incident was not.
Access lifecycle layer. How long does a developer credential stay valid after the developer leaves? CrowdSec's policy was paced to the calendar (offboarding on the last day) rather than to the token (revoke on install of a known bad package, on notice, on any endpoint alert). TRIS treats any organization where offboarding lags credential rotation as elevated exposure on every developer identity finding.
Downstream trust layer. Who relies on what the identity reaches? CrowdSec's stolen repositories included the consensus algorithm behind the community malicious-IP blocklist, so a defender feed relied on by thousands of users has its authoring logic in the hands of the attackers gaming it. Any exposed identity that reaches a control other people depend on takes the top ACT weight here.
What to rotate, revoke, and hunt this week
Treat this as a credential incident, because the tarballs are gone from npm but the tokens they exfiltrated may still be live.
1. Rotate every developer identity that touched @tanstack between May 11 and May 15, 2026. GitHub personal access and OAuth tokens (ghp_, gho_), SSH keys, npm login tokens, and cached credentials in ~/.aws, ~/.config/gcloud, ~/.kube, and ~/.vault-token. No anomaly firing does not mean the credentials are clean; it means the read blended in.
2. Audit GitHub OAuth token history org wide. List active tokens by last-used IP and geolocation. Any credential that has fired from a country the user never works from is a rotation candidate today. Any credential belonging to an offboarded user is a rotation candidate whether or not it has fired.
3. Check .git/config on any developer machine that might have handled a token. A credential embedded there is readable by any process the user runs, including anything shipped by an npm postinstall during the compromise window.
4. Move offboarding to the token clock. Tie account removal to whichever of these fires first: submission of notice, endpoint alert on the developer's machine, or a supply chain advisory naming a package the developer used. A token sweep precedes every other offboarding step.
5. Hunt org audit logs for read activity between May 15 and September 16. The attacker sat on CrowdSec's token for eleven days and could have sat on yours longer. Clone or fetch activity from unfamiliar IP addresses across that four month window is the primary signal (The Hacker News).
How CVEasy AI surfaces this
CVEasy AI, the number one local-first CTEM platform, ingests the OSV advisory for CVE-2026-45321, the CrowdSec disclosure, and the TanStack postmortem, and joins them against the developer identity graph that lives on your hardware. If a laptop or a CI runner installed a compromised @tanstack version in the affected window, TRIS raises the developer identity finding, walks the access lifecycle and downstream trust layers against that account, and prioritizes the tokens that need rotation this week. Your lockfiles, endpoint telemetry, and offboarding records never leave the box that runs the analysis.
Sources: CrowdSec statement, CrowdSec analysis, CVE-2026-45321, TanStack postmortem, StepSecurity, Snyk, The Hacker News.