TeamPCP Breached GitHub Itself Over Memorial Day Weekend. The Fifth Indirect-Trust Vector Is The VS Code Extension. We Predicted The Doctrine Would Spread.
- Patrick Duggan
- 1 minute ago
- 6 min read
Three days ago I published a blog naming three indirect-trust supply-chain vectors that had hit corporate developers in three weeks: Laravel-Lang tag-pointer compromise, Megalodon GitHub Actions workflow injection, Ghost CMS theme execution primitive. A few hours later, while back-filling adversary profiles, we surfaced a fourth — the Polymarket Bot supply-chain attack through a hijacked verified GitHub organization, attributable to a distinct actor cluster but using the same structural primitive. The closing line of that fourth-vector post was: "Four vectors in three weeks. The doctrine has compounded. The next campaign that fires will use one of the same four vectors, or a fifth that fits the same shape."
Three days later — over the U.S. Memorial Day long weekend, when American IT security teams are at minimum staffing — TeamPCP, the cluster behind the Megalodon GitHub Actions campaign, breached GitHub itself. The vector is the fifth one. The attack mechanic is a poisoned Nx Console Visual Studio Code extension that was live on the Microsoft Visual Studio Marketplace for exactly eighteen minutes between 12:30 and 12:48 UTC on May 18, 2026. During that window, the trojanized extension was downloaded by enough developers — including at least one GitHub employee — to give TeamPCP credential access that ultimately resulted in the cloning of approximately 3,800 GitHub-internal private repositories. GitHub has now confirmed the incident. CVE-2026-48027 has been allocated. Sophos Managed Detection and Response recovered the post-compromise Python backdoor, cat.py, from an affected endpoint. The actor identifies itself publicly on X under the handle xploitrsturtle2 and has listed the stolen data for sale on a cybercrime forum.
This post is the prediction-verification entry. We did not predict this specific campaign. We predicted the doctrine would extend. The doctrine extended exactly the way the structural argument said it would.
The fifth vector named precisely
The Nx Console extension is the IDE-plugin layer that automates Nx monorepo tooling for Angular and React developers. Roughly two million developers use it in active deployments. It is exactly the kind of trusted, daily-use, auto-updating developer-tooling artifact that the indirect-trust doctrine identifies as the highest-value target: a layer between the developer and the code that the developer does not audit between releases. The poisoned version, 18.95.0, looked and behaved like normal Nx Console. On startup it silently ran a single shell command that downloaded a hidden payload from a planted commit on the official nrwl/nx GitHub repository. That payload was a credential stealer that ran in the background. The harvest list is comprehensive: GitHub personal access tokens, npm authentication from .npmrc, AWS credentials from instance metadata and environment variables, HashiCorp Vault tokens, Kubernetes service-account secrets, 1Password CLI sessions, SSH private keys, cloud provider configuration files, and — notably — AI tool credentials including Claude Code configuration files. Exfiltration ran over HTTPS, the GitHub API, and DNS tunneling. Persistence was established on macOS targets via a Python backdoor planted at /Users/%/.local/share/kitty/cat.py.
The initial-access vector for the attack on the Nx contributor's GitHub token, used to publish the trojanized extension, came from a prior supply-chain compromise of the TanStack npm packages. The chain of compromise is therefore: TanStack npm packages → stolen Nx contributor's GitHub token → poisoned Nx Console extension uploaded → 18-minute live window on Visual Studio Marketplace → GitHub employee installs or auto-updates → credential stealer harvests GitHub session → attacker uses the harvested credentials to clone 3,800 internal GitHub repositories.
Five indirect-trust layers stacked in one operation. Each layer was an artifact that the layer below trusted without auditing. Each layer was the developer's-own-tooling primitive. The trust topology was the attack topology.
The eighteen-minute window is the new tradecraft
The decision to leave the trojanized extension live for only eighteen minutes is operationally significant. Eighteen minutes is short enough that most signature-based marketplace scanners will not catch the upload within the window. It is long enough to receive auto-update pulls from any client that polls the marketplace at standard intervals. It is also short enough to defeat any retrospective "the bad version was online for X days, here is who downloaded it" customer-notification process — by the time the marketplace pulls the bad version, the auto-update pulls have already shipped the payload to whoever was set to update. The attack is therefore engineered to harvest the population of automatic-update clients while leaving the population of manual-install clients largely untouched. That is a deliberate tradecraft choice that biases the attack toward enterprise developers (who tend to leave auto-update on for productivity reasons) rather than security-conscious individual developers (who often disable auto-update).
This is the new tradecraft signature for the indirect-trust doctrine class. Expect to see it again. The next campaign will plant a poisoned package, leave it live for fifteen to thirty minutes, take it down voluntarily, and then claim the takedown as evidence that the marketplace caught it. The actual exploitation window will have been the entire auto-update interval of the targeted clients, which is hours longer than the live-listing window.
TeamPCP, again, and the AI-credentials targeting
This is the fourth campaign in our IOC corpus attributable to TeamPCP within an eight-week window: container compromise via Cipherforce-class scanning, Trycloudflare-tunneled Canisterworm payload delivery, the Megalodon GitHub Actions mass-poisoning of 5,561 repositories, and now the Nx Console / GitHub-internal breach. Their tradecraft has been consistent across all four: target the developer-tooling artifact, harvest cloud and credential surfaces, exfiltrate through legitimate-looking channels, monetize through public claims and forum listings. The cluster is increasingly the canonical exemplar of the doctrine the broader criminal market is internalizing.
The detail that matters most for our specific operating posture is that the credential stealer targets Claude Code configuration files explicitly. Claude Code stores its session state and any model-routing or API-key configuration in a .claude/ directory under the user homedir. TeamPCP's stealer was tuned to harvest that directory. Every developer running Claude Code on a machine that installed the poisoned Nx Console version between 12:30 and 12:48 UTC on May 18 has a compromised Claude Code session credential. We did not see this fire against our environment because we did not auto-update Nx Console during the window. The general case for the broader Claude Code user base is less reassuring: the only path-of-prevention was the absence of the trojanized extension during eighteen minutes on a specific Monday.
Anthropic has not, as of this writing, issued specific guidance on Claude Code credential rotation in response to the TeamPCP breach. The reasonable defender posture is to rotate any Claude Code API keys that were active on a developer machine running Nx Console between May 18 and May 26, treat any session that was open during that window as suspect, and re-audit any Claude Code action history for unexpected calls.
The structural prediction the doctrine post made, now verified
Three blog posts and one back-fill in the last four days described the indirect-trust doctrine, named the four vectors that had already fired, and predicted that the next campaign would use one of the same vectors or a fifth that fits the same shape. The fifth vector landed within seventy-two hours of that prediction. The actor was the same actor we had just added to the adversaries index. The target was GitHub itself.
This is not because our prediction was clever. It is because the doctrine the criminal market has internalized is structurally inevitable: every layer of indirect trust in the developer toolchain is exploitable, and the marketplace is working through the layers in roughly the order of leverage they offer. Tags, workflows, themes, organizations, IDE extensions. The next layer in the sequence is the developer's actual editor — and by extension, the AI coding assistants integrated into the editor. The poisoned Claude Code configuration harvest in the current breach is precisely that movement.
The defender primitive that has worked across every previous indirect-trust attack also works for this one: pin to behavior, not destination; audit the indirect-trust artifact layer with the same skepticism applied to the primary artifact; rotate credentials on any window of indeterminate exposure rather than waiting for evidence of compromise. The 49-day lead time we had on the original Megalodon C2 was structural — the data was in the corpus, the detector was the missing piece. The same structural argument applies here. The data on the next campaign is in someone's corpus right now. The detector has not been written yet.
The receipt is timestamped. The doctrine is operational. The next vector is already staging.
How do AI models see YOUR brand?
AIPM has audited 250+ domains. 15 seconds. Free while still in beta.
