GitHub Got Hacked. The Real Threat Is TeamPCP.
On May 19, 2026, GitHub itself lost 3,800 internal repos to a poisoned VS Code extension on one employee's laptop. The same group, TeamPCP, hit Trivy in March and TanStack in May. What's actually new about the 2026 supply chain campaign, and what your engineering team should do this week.
On May 19, 2026, the company that hosts the world’s code got hacked. Not through a zero-day in a load balancer, not through a sophisticated nation-state intrusion. Through a VS Code extension installed by one employee. About 3,800 internal repositories exfiltrated. GitHub confirmed it publicly at 6:25 AM PDT on May 20.
If you read that as a one-off, you’re missing the bigger story. The same group — TeamPCP, also tracked as UNC6780 — has been running the same playbook against developer tooling all year. Trivy in March. CheckMarx KICS. LiteLLM. Telnyx SDK. TanStack on May 11. The European Commission’s cloud infrastructure. Now GitHub itself.
This is the first credible end-to-end campaign that breaks the assumptions every engineering team built their dependency posture on. The signing didn’t help. The provenance didn’t help. The reputable maintainers didn’t help. The audit-friendly CI didn’t help. Here’s what changed, why, and what to do this week.
The four incidents that connect
Trivy (Aqua Security) — March 19, 2026. An attacker exploited an incomplete credential rotation following an earlier pull_request_target misconfiguration. With a single surviving PAT, they took over the aqua-bot service account and force-pushed 75 of 76 version tags in aquasecurity/trivy-action to malicious commits. Any workflow pinned to @v0.28.0 or any version tag started executing attacker code without a single file in the repository changing. The malware scraped Runner memory for SSH keys, AWS/GCP/Azure credentials, Kubernetes tokens and database passwords, encrypted with AES-256-CBC + RSA-4096 wrapping, and exfiltrated through typosquatted domains and GitHub repository dead-drops. Persistent backdoor (sysmon.py as a systemd service) on developer machines used ICP blockchain C2. A separate worm — CanisterWorm — self-propagated into 47+ npm packages. (Palo Alto Networks)
TanStack — May 11, 2026, 19:20 UTC. Within six minutes, 84 malicious artifacts across 42 @tanstack/* packages were published, including @tanstack/react-router (12.7M weekly downloads). The attack chain: a fork triggered bundle-size.yml via pull_request_target, executing attacker-controlled code in the base repository’s trust context. That code poisoned the pnpm store cache with a precomputed key, persisting eight hours. When the legitimate release.yml ran on main, it restored the poisoned cache. Attacker binaries then located the GitHub Actions Runner.Worker process via /proc/*/cmdline and dumped memory from /proc/<pid>/mem to extract the OIDC token, publishing to npm directly while bypassing the workflow’s own publish step. This is the first documented case of a malicious npm package carrying valid SLSA Build Level 3 provenance. Sigstore verified the build correctly. What SLSA doesn’t guarantee is that the code being built is safe. (TanStack postmortem, Snyk)
GitHub itself — disclosed May 20, 2026. A poisoned VS Code extension on one employee’s laptop. Full access to all credentials on that device. 3,800 internal repositories exfiltrated. GitHub has not yet named the extension. TeamPCP claimed responsibility and began selling the data on cybercrime forums. GitHub rotated critical secrets, isolated the endpoint, and says it has no evidence customer data outside internal repositories was touched — investigation ongoing. (TechCrunch, SecurityWeek, Help Net Security)
Mini Shai-Hulud worm — running across the campaign. TeamPCP’s self-replicating payload propagates through stolen CI/CD credentials, enumerating other packages each compromised maintainer can publish and republishing them with identical injection logic. Persistence vectors include Claude Code hooks in .claude/settings.json, VS Code workspace tasks in .vscode/tasks.json, systemd services on Linux and LaunchAgents on macOS — some of which destroy home directories if the GitHub token is later revoked.
This isn’t four breaches. It’s one campaign with one operator, hitting four trust boundaries.
What’s actually new
The target is the pipeline, not the product. Most prior supply chain attacks targeted the dependency (left-pad, event-stream, ua-parser-js). These target the automation that builds, signs and publishes the dependency. The compromised artifact is identical in every way to a legitimate release because it was a legitimate release — produced by the maintainer’s own keys, on the maintainer’s own infrastructure, with the maintainer’s own provenance attestation. There’s nothing to verify against.
Memory scraping in CI runners is the default playbook now. GitHub Actions runners hand a short-lived OIDC token to workflows for cloud authentication. The token lives in process memory. If you can run any code in the runner’s user context, you can read it. The TanStack attack proved this works in production, at scale, against a maintainer who was doing nothing obviously wrong. The defensive answer — ephemeral runners with strict process isolation — is not what most repos use.
SLSA provenance is a useful signal that’s now actively misleading. Sigstore signs what the build produced. It does not validate the inputs. If the cache was poisoned, the binary that gets signed is malicious — and the signature is mathematically valid. Provenance + signing remains necessary (it lets you trace which build produced which artifact) but it is no longer sufficient (you can’t infer safety from a valid attestation alone). Every “verify the signature” tutorial written before May 2026 needs an asterisk.
Persistence is now via developer tools, not malware-as-malware. VS Code extensions, Claude Code hooks, the workspace tasks.json, npm postinstall scripts — these all run code on the developer’s machine, with the developer’s permissions, when the developer opens the repo. They’re harder to detect than traditional implants because they look exactly like the legitimate productivity tooling they impersonate. The Trivy worm’s systemd service that wipes $HOME when the GitHub token gets revoked is a small but telling detail: the operator wants you to keep the token live.
The blast radius compounds across attacks. Trivy got popped → Trivy users’ CI secrets got stolen → those secrets included npm publish tokens → 47+ packages downstream got compromised → those packages got installed in thousands of CI runs → more secrets stolen → more packages compromised. Mini Shai-Hulud automated the propagation. By the time TanStack happened, the attacker had thousands of stolen tokens. By the time GitHub happened, they had a foothold in someone’s VS Code extension supply chain. Each successful hop fed the next.
What broke about your defenses
If you wrote down your supply chain security posture in 2024 and haven’t revisited it in 18 months, here’s what’s now stale:
- “We pin our dependencies to versions.” Versions are tags. Tags can be force-pushed. The Trivy attack didn’t change a single workflow file — it changed where existing version tags pointed. You need to pin to immutable commit SHAs, not tags.
- “We trust signed packages from reputable maintainers.” The TanStack maintainers are legitimate and the packages were signed. The signing key was the runner’s OIDC token, lifted out of memory. Reputation is not a defense against an attack on the maintainer’s pipeline.
- “We have SBOM and SLSA L3.” SLSA L3 produces a verifiable record of what the pipeline built. It says nothing about whether the inputs to that pipeline were trustworthy. You still need separate verification of the source code you’re building.
- “Our CI is private.” GitHub Actions runners in private repos are not isolated from public forks if you use
pull_request_target. The Pwn Request pattern is now mainstream tooling for attackers — not a theoretical concern. Audit everypull_request_targetin every workflow this week. - “Our developers only install reputable VS Code extensions.” The extension marketplace is not adversarially curated. Microsoft validates publisher identity and signs the extension binary; they do not audit the JavaScript that runs when you install. Anything you install gets full access to your shell, your cookies, your SSH agent and your cloud SDKs.
What actually works (do this week)
Pin every external GitHub Action to a commit SHA. Not @v4, not @latest. The full SHA. Use Dependabot to update SHAs through PRs you actually review. Time cost: one engineer for a day on a normal repo.
# bad — points at a tag attacker can force-push
- uses: aquasecurity/[email protected]
# good — points at an immutable commit
- uses: aquasecurity/trivy-action@f78e9ecf42a1a4af5e6d2d3f3e8a9e2d1b3c4d5e6
Eliminate pull_request_target unless you can fence it. If you need it for benchmarks or labels, restrict it with if: github.event.pull_request.head.repo.full_name == github.repository and never check out the PR’s code. Treat pull_request_target workflows as if they ran with your most sensitive secret, because they effectively do.
Move to ephemeral runners with no persistent cache. GitHub-hosted runners are ephemeral by default — that’s good. But the cache is shared across workflows. Audit which workflows use actions/cache and what paths they cache. The TanStack attack worked because the pnpm store was a shared cache across branches. Either don’t cache anything secret-adjacent, or scope cache keys per branch/workflow with hash isolation.
Workload identity per repo, not org-wide. If you use OIDC to authenticate from GitHub Actions to AWS/GCP, the trust policy on the cloud side should pin to the specific repository and workflow, not repo:org/*. The TanStack OIDC trust policy was overly permissive — fixing it would have made the stolen token useless.
Audit developer machine extensions. This week, dump the VS Code extension list from every engineer’s machine. For each extension: who’s the publisher, when was it last updated, does it ask for unusual permissions, do you actually use it. Uninstall everything you don’t actively use. There is no “small” extension on a dev machine — they all run JavaScript with your shell privileges.
Rotate every secret that’s ever touched a CI runner. If you’ve used Trivy, TanStack Router, or any package downstream of them in CI in the last 90 days, assume the runner’s memory was readable. Rotate npm publish tokens, cloud OIDC bindings, repo secrets, SSH deploy keys. It’s painful. It’s also a lot less painful than the alternative.
Verify provenance — and separately audit source. Sigstore + SLSA still matters. But add a step that builds the package from source in your own isolated environment and diffs the result against the published artifact. This catches cache poisoning. Several tools do this today; Snyk, Aikido and StepSecurity all ship variants.
Subscribe to your dependencies’ security advisories. GitHub Security Advisories, npm advisories, the Open Source Security Foundation’s OSV database. Most of these attacks were public within an hour. Most of the impact happens to teams who learned about them three days later from a blog post.
What we’re doing for clients this week
Every Softronic client with a Cybersecurity retainer is getting an emergency supply chain audit this week. Scope:
- Full inventory of GitHub Actions in active workflows, with pinning status (SHA vs tag).
pull_request_targetaudit — every workflow, every guard, every checkout.- Workload identity trust policies on AWS/GCP — every binding, narrowed to specific workflows.
- VS Code extension inventory per engineer machine, with risk scoring.
- Secret rotation list with priority order.
- A runbook for what to do if a dependency in your tree was named in any 2026 TeamPCP advisory.
This is 8–16 hours of work per client, depending on repo size. It’s included in the existing $4K/mo retainer scope, not an upsell. If you’re not on a retainer with us and you want this work done as a one-off engagement, it’s a $3,500 fixed-fee for the full audit, runbook and remediation list — turnaround 5 business days.
Pricing summary
- Supply chain emergency audit: $3,500 fixed-fee, 5 business days, full audit + remediation runbook.
- Pentest: from $8K for focused web app, $15-25K for app + cloud + network.
- Security retainer: from $4,000/mo. Now includes supply chain hygiene as part of the standard scope.
Bottom line
You can no longer infer the safety of a dependency from the reputation of the maintainer, the validity of the signature, or the presence of provenance. The 2026 supply chain campaign — TeamPCP, Mini Shai-Hulud, and what comes after — has made the build pipeline itself the attack surface. The engineering work to defend it is unglamorous: pin SHAs, fence pull_request_target, scope OIDC trust, audit your tools. We’ve been doing this work since March. If you want help getting it done this week, start an engagement. Discovery call is free.