June 16, 2026
How TeamPCP Spent 10 Weeks Building Up to GitHub’s Worst Day
The most methodical supply chain campaign of 2026 didn’t start with GitHub. It started with a security scanner — and nobody connected the…
freerave
8 min read
- 1 The most methodical supply chain campaign of 2026 didn't start with GitHub. It started with a security scanner — and nobody connected the dots until it was too late.
- 2 Who Is TeamPCP?
- 3 The Campaign: Ten Weeks of Escalation
- 4 Week One: The Opening Gambit (March 19)
- 5 Demonstrating New Capabilities (March 26–27)
The most methodical supply chain campaign of 2026 didn't start with GitHub. It started with a security scanner — and nobody connected the dots until it was too late.
On May 20, 2026, GitHub published a short statement confirming what the security community had already begun to piece together: a threat group called TeamPCP had exfiltrated approximately 3,800 of GitHub's own internal repositories.
The initial access vector was a VS Code extension. It was live on the Marketplace for eighteen minutes.
I've spent the past several days pulling apart the full campaign — from the first npm package in March to the GitHub breach in May. What emerges is not a story about a clever zero-day or a sophisticated exploit chain. It's a story about patience, escalation, and an attack doctrine that treats the developer workstation as the only perimeter that matters.
Who Is TeamPCP?
Before the timeline, you need to understand who you're dealing with — because this group is not what most people imagine when they picture a supply chain attacker.
TeamPCP (tracked by Google Threat Intelligence as UNC6780, also operating as PCPcat, DeadCatx3, and ShellForge) is a financially motivated cybercrime organization. No geopolitical agenda. No nation-state backing. Pure profit motive — credential theft, data sales, extortion.
What separates them from the average criminal operation is their engineering discipline.
Their malware families share a lineage. Wiz's threat intelligence team confirmed high-confidence attribution through a shared RSA public key reused across the Trivy, Telnyx, and Nx Console payloads. Their cipher salts are consistent across campaigns. Their dead-drop URL patterns follow an identifiable template. They don't improvise. They iterate.
They also build for resilience. Their command-and-control infrastructure runs on ICP blockchain canisters — a decentralized compute layer that cannot be taken down by domain seizure or IP blocking. Once planted, their beacons persist through infrastructure takedowns that would kill a traditional C2.
One more detail worth noting: their payloads include a check for Russian locale (LANG=ru_RU) and skip execution on those systems. This is a standard operational security pattern for Eastern European cybercrime crews — protect your neighbors, target everyone else.
The Campaign: Ten Weeks of Escalation
Week One: The Opening Gambit (March 19)
The campaign began with Aqua Security's Trivy — the most widely deployed open-source vulnerability scanner. Hundreds of thousands of CI pipelines pull Trivy on every build, making it a near-perfect supply chain entry point.
The vector was mundane: incomplete credential rotation following a prior incident. TeamPCP used stale Trivy publish credentials to force-push malicious commits across 76 of 77 version tags in aquasecurity/trivy-action.
The payload was anything but mundane. CanisterWorm used ICP blockchain canisters as C2 — a first-of-kind capability in a publicly documented npm supply chain attack. Any CI pipeline that ran a Trivy scan during the compromise window had its credentials harvested and a persistent beacon installed.
The industry noticed. Then moved on.
Demonstrating New Capabilities (March 26–27)
Within days, TeamPCP demonstrated two techniques that would appear throughout the campaign.
Against LiteLLM (the AI gateway sitting between apps and providers like Anthropic and OpenAI), they deployed a three-stage payload with a novel persistence mechanism: a .pth file in Python's site-packages directory. This is an elegant attack. Any .pth file in that directory executes on every Python interpreter invocation — not on import, not on install, but every time python runs anywhere on the system. It survives virtual environment deletion. It survives pip uninstalling the original malicious package. It is invisible to developers who don't know to look for it.
Against Telnyx, they hid a Windows PE binary inside a .WAV audio file using steganography. The SDK fetched the audio file from C2, extracted the payload via XOR decryption, and executed it in memory. Most egress filters and corporate DLP tools simply do not inspect audio files for executable content. That's the entire point.
The Scale Statement (March 31)
The axios compromise was designed to make one thing clear: TeamPCP could reach anyone.
Axios handles roughly 100 million npm downloads per week. It is embedded in React applications, Node.js backends, build pipelines, and serverless functions across essentially the entire JavaScript ecosystem. At 19:41 UTC on March 31, two malicious versions appeared on npm — each carrying a cross-platform RAT targeting macOS, Windows, and Linux.
They were live for approximately three hours.
I won't pretend to know how many machines were affected. Neither can anyone else. Three hours, 100 million weekly downloads, and an ecosystem built on automated npm install in CI pipelines. The math is uncomfortable.
The Worm Learns to Walk (April 27)
The @bitwarden/cli compromise introduced the capability that would define the campaign's final phase.
The malicious package didn't just steal credentials. On execution, it automatically enumerated every npm package the victim's stolen token could publish, injected malicious code into each one, and re-published them — all without human intervention. One stolen publish token could cascade into hundreds of poisoned downstream packages before a single alert fired.
This is the Shai-Hulud architecture. It is not a supply chain attack in the conventional sense. It is a supply chain worm: self-propagating, automatic, and exponential.
The Cross-Registry Strike (April 29 — May 1)
Over 48 hours spanning April 29 and May 1, TeamPCP coordinated simultaneous strikes across npm, PyPI, and RubyGems — hitting SAP's Cloud Application Programming Model, PyTorch Lightning, and intercom-client in a single operation.
Three registries. One coordinated window. Combined monthly reach: over 10 million installs.
The Technique That Needed No Credentials (May 11)
The TanStack compromise is the most technically significant moment in the campaign — not because of the damage, but because of how they got in.
They did not steal credentials. They did not compromise an account. They exploited a GitHub Actions misconfiguration that exists, in some form, in a significant percentage of open-source projects.
Here's the attack, simplified: TanStack's CI ran a workflow triggered by pull requests, including pull requests from forks. That workflow had write access to the repository's Actions cache. TeamPCP opened a PR from a fork, used their code execution in the workflow to poison the cache with malicious build artifacts, and waited. When TanStack's maintainers ran a legitimate release, the poisoned cache contaminated the published packages.
Between 19:20 and 19:26 UTC on May 11, 84 malicious package versions were published across 42 @tanstack/* packages. Six minutes.
The confirmed victims: OpenAI (two employee devices compromised, code-signing certificates rotated) and Mistral AI (one developer device, $25,000 extortion demand for a claimed 5GB source code leak).
The Campaign Goes Open Source (May 13)
In a move that fundamentally changed the threat landscape, TeamPCP published the complete Shai-Hulud worm source code to GitHub under the MIT license — alongside a $1,000 Monero prize on BreachForums for the best supply chain attack built on the codebase.
Within days: the first documented copycat campaign, using the Shai-Hulud source, publishing four malicious npm packages.
TeamPCP had not just run a supply chain campaign. They had built a supply chain attack framework and made it freely available to anyone motivated enough to use it.
May 18, 12:30 UTC
Everything above was, in retrospect, preparation for this.
At 12:30 UTC on May 18, a malicious version of nrwl.angular-console — the official Nx Console VS Code extension, 2.2 million installs, verified publisher — appeared on the VS Code Marketplace.
The community detected it at 12:41 UTC. It was pulled at 12:48 UTC.
Eighteen minutes.
The Payload
The malicious main.js was architecturally clean. Within seconds of loading any workspace, it fetched a 498KB obfuscated payload. That payload was not hosted on an attacker-controlled domain — it lived on an orphan commit inside the official nrwl/nx GitHub repository.
An orphan commit has no parent. It doesn't appear in any branch. It doesn't surface in git log. Standard code audits miss it. Most security scanners miss it. But it's accessible via its SHA — and because it lives on raw.githubusercontent.com, it passes proxy inspection, satisfies CSP policies, and raises no egress alerts.
The payload targeted: 1Password vaults, GitHub tokens, npm auth tokens, AWS credentials, and Anthropic Claude Code configurations. Everything a developer authenticates to in the course of a normal workday.
The GitHub Breach
On May 19, GitHub detected the anomaly. On May 20, they confirmed the scope: approximately 3,800 internal repositories exfiltrated.
TeamPCP listed the material on a criminal forum at over $50,000.
GitHub's incident response was, by any fair measure, fast: same-day detection, sub-24-hour public disclosure, immediate credential rotation. The structural questions their response raises have nothing to do with how they responded — and everything to do with how the situation was possible at all.
A single developer endpoint. Access to 3,800 internal repositories. Auto-updating VS Code extensions running in that environment.
The blast radius of one compromised laptop should not reach 3,800 repositories. That's an architectural gap, not a policy gap.
The Doctrine
Across ten weeks, TeamPCP demonstrated a coherent attack philosophy that is worth naming explicitly, because it represents where the threat landscape has settled.
The trust is the exploit. No CVE needed. No firewall to bypass. Every vector in this campaign — a security scanner, an AI gateway, a password manager, a UI framework, an IDE extension — was something developers already trusted completely. The attack didn't break through the perimeter. It walked in through the front door wearing trusted credentials.
Self-propagation changes the math. Traditional supply chain attacks are linear: compromise maintainer, poison package, wait. Shai-Hulud is exponential: steal one publish token, automatically infect every package that token can reach, those infections steal more tokens, repeat. By the time detection happens, the graph of compromise is already wide.
The developer workstation is the perimeter. This is the threat model inversion that the industry has been slow to act on. The datacenter may be hardened. The developer laptop running an IDE with forty auto-updating extensions, simultaneously authenticated to GitHub, npm, AWS, and a password manager, is where the real exposure lives in 2026.
What Actually Needs to Change
I'll be specific, because vague recommendations don't help anyone.
On the GitHub Actions front: Audit every workflow triggered by pull_request that has actions: write permissions or inherits broad defaults. This is the exact misconfiguration that compromised TanStack. The fix is explicit least-privilege permissions on every job — contents: read, no write access unless specifically required. Pin Actions dependencies to full commit SHAs rather than mutable version tags.
On the VS Code front: Disable automatic extension updates on any machine that holds production credentials. This is not a minor inconvenience. It is the specific technical control that would have prevented the GitHub breach. Manual update review takes thirty seconds per extension.
On the Python front: Audit .pth files in every Python environment you maintain. The LiteLLM persistence mechanism plants files in site-packages that survive package uninstalls. If you have .pth files you didn't explicitly create, investigate.
On the credential architecture front: npm publish tokens should be scoped to specific packages, not entire account portfolios. A stolen token that can only publish my-specific-package cannot be used to poison your entire ecosystem. This is the structural control that limits Shai-Hulud's propagation.
If you ran Nx Console on May 18 between 12:30 and 12:48 UTC with auto-update enabled: Treat your GitHub tokens, npm tokens, AWS credentials, 1Password vault, and Anthropic API keys as compromised. Rotate before you do anything else.
A Final Observation
The developers who came through this campaign without incident weren't necessarily faster or more alert. They had made architectural decisions — explicit token scoping, extension allowlisting, least-privilege CI, minimum-age package install policies — that limited the blast radius of any single compromise before the attack arrived.
Security in 2026 is not about detecting attacks faster. It is about ensuring that when — not if — one endpoint is compromised, the damage it can do is bounded by design.
The eighteen minutes Nx Console v18.95.0 was live on the Marketplace caused a breach affecting 3,800 internal GitHub repositories because there was no architectural control limiting what a compromised developer endpoint could reach.
Architecture doesn't just beat prompts. It beats patches. It beats detection. It beats incident response.
Build the system that limits the damage first. Then worry about everything else.
Technical details sourced from OX Security, Wiz, StepSecurity, Akamai, Socket, Palo Alto Unit 42, Sophos, and Hackread public disclosures through May 20, 2026. Attribution follows Wiz (high confidence via RSA key match) and StepSecurity/Socket .