TanStack CI/CD Release Pipeline Poisoning
On May 11, 2026, the popular open-source project TanStack fell victim to a CI/CD release pipeline poisoning attack. Threat actors hijacked the release pipeline via a pull request exploitation vector and OIDC token theft to publish 84 backdoored versions across 42 packages.
- Date:
- Severity:
- critical
- Sources:
- 4
Executive Summary
On May 11, 2026, the highly popular open-source project TanStack (used widely for state management, routing, and data fetching) fell victim to a highly sophisticated CI/CD pipeline poisoning attack TanStack Advisory. The threat actor group TeamPCP (also tracked as UNC6780) bypassed direct registry controls by exploiting a pull_request_target “Pwn Request” vulnerability and GitHub Actions cache poisoning Snyk Research. This allowed them to hijack the automated release pipeline and publish 84 backdoored versions across 42 legitimate @tanstack/* npm packages TanStack Advisory. The malicious versions executed a credential-stealing loader (router_init.js) during package installation, which subsequently led to the compromise of downstream development assets—most notably, the theft of an Nx contributor’s GitHub CLI credentials StepSecurity. Defenders must immediately isolate affected environments and clean local persistence files before attempting to rotate credentials to prevent triggering destructive “dead man’s switches” TanStack Advisory.
Key Facts
threat_type: CI/CD compromise, GitHub Actions compromise, poisoned release, artifact tampering, credential theft, token exfiltration
ecosystem: npm
registry: npmjs.com
affected_packages:
- "@tanstack/zod-adapter"
- "@tanstack/router"
- "@tanstack/react-router"
- "@tanstack/react-query"
- "@tanstack/table-core"
malicious_versions:
- "1.166.12"
- "1.166.15"
fixed_versions:
- "1.166.16"
- "1.166.17"
safe_versions:
- "v1.166.16 and later"
exposure_window: 2026-05-11T19:20:00Z to 2026-05-11T20:15:00Z (55 minutes)
execution_trigger: install-time execution (npm lifecycle scripts)
primary_impact: Credential theft (AWS/GCP tokens, npm configs, SSH keys, GitHub PATs) and lateral worm propagation
known_iocs:
- "router_init.js"
- "ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c"
- "git-tanstack[.]com"
confidence: high
canonical_source: https://tanstack.com
Source Confidence & Evidence Mapping
- confirmed: Hijack of GitHub Actions automated release pipeline via a pull request exploitation vector, resulting in 84 backdoored releases across 42
@tanstack/*npm packages. TanStack Advisory - likely: Chaining of
pull_request_targetworkflow vulnerabilities and cache poisoning to forge signed OIDC identity tokens, enabling authorized publishing to the npm registry. Snyk Research - unclear: The complete list of developer environments or downstream organizations that downloaded and executed the malicious version during the 55-minute exposure window.
- not_observed: No direct maintainer account passwords or active MFA sessions were bypassed; the threat actor interacted solely with the automated pipeline’s credentials.
Timeline
- 2026-05-11T19:20:00Z Attackers submit a malicious pull request, triggering the poisoned GitHub Actions workflow. Source: Snyk Research
- 2026-05-11T19:23:00Z Attackers successfully poison the GitHub Actions runner cache and extract valid OIDC identity tokens. Source: StepSecurity
- 2026-05-11T19:26:00Z First batch of 84 malicious
@tanstack/*packages (including@tanstack/zod-adapter@1.166.12) are published to npmjs.com. Source: TanStack Advisory - 2026-05-11T19:45:00Z Maintainers detect anomaly in automated release logs and initiate active incident response. Source: TanStack Advisory
- 2026-05-11T20:15:00Z npm registry removes the 84 backdoored versions and revokes the associated publishing tokens. Source: TanStack Advisory
- 2026-05-11T20:30:00Z TanStack releases clean, official patches (e.g.,
@tanstack/zod-adapter@1.166.16) and issues an all-clear. Source: TanStack Advisory - 2026-05-11T21:00:00Z Official security advisory is published under tracking ID GHSA-g7cv-rxg3-hmpx. Source: GHSA Database
What Happened
On May 11, 2026, the threat group TeamPCP compromised the trusted release flow of the @tanstack/* project Snyk Research. By crafting a pull request that triggered a poorly isolated pull_request_target GitHub Actions runner, the attackers executed malicious code within a privileged context StepSecurity. The runner’s OIDC tokens were intercepted, allowing the attackers to authenticate directly to the npm registry as a trusted publisher Palo Alto Networks. Within minutes, the attackers pushed 84 compromised packages before maintainers noticed the rogue build logs and intervened to take down the releases TanStack Advisory.
Technical Analysis
Initial Access
Initial access was achieved via a “Pwn Request” targeting the project’s GitHub Actions workflow StepSecurity. The workflow, configured with pull_request_target permissions, allowed untrusted forks to execute code with access to repository secrets and OIDC scopes. The attacker poisoned the GitHub Actions runner cache, inserting a malicious dependency loader that hijacked subsequent release stages.
Package or Artifact Manipulation
The attackers did not modify the main branch codebase. Instead, they manipulated the build runtime, injecting a malicious payload loader directly into the build artifact compilation step. The resulting package tarball included an injected optionalDependencies pointer redirecting to a rogue fork ("@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c") and planted a heavily obfuscated payload named router_init.js in the root of the packages Snyk Research.
Execution Trigger
The malware utilized npm install lifecycle hooks (e.g., preinstall or postinstall script triggers) defined in package.json. Upon running npm install on a developer workstation or a CI runner, Node.js executed the lifecycle hooks, launching router_init.js through the system shell.
Payload Behavior
The payload, router_init.js (a ~2.3 MB obfuscated loader), functioned as a credential-harvesting worm (“Mini Shai-Hulud”) Palo Alto Networks. Once active, it profiled the host environment, searching for local files containing secrets. It harvested:
- AWS, Azure, and Google Cloud API credentials
- Kubernetes service account tokens
- HashiCorp Vault access configurations
- Local
.npmrcpublishing tokens - SSH private keys
- GitHub personal access tokens (PATs) and
ghCLI OAuth sessions
The malware also established persistence via local .vscode/tasks.json configurations and macOS LaunchAgents (gh-token-monitor). To deter response efforts, the payload monitored for token revocation and featured a destructive “dead man’s switch” capable of wiping filesystems if its access was severed TanStack Advisory.
Exfiltration / C2
domains:
- "git-tanstack[.]com"
ips: []
urls:
- "hxxps://git-tanstack[.]com"
protocols:
- "https"
- "session"
endpoints:
- "/api/v1/exfil"
confidence: high
Stolen secrets were exfiltrated via HTTPS to the typosquatted C2 server git-tanstack[.]com and routed securely over the decentralized Session/Oxen messenger network.
Propagation
The malware featured autonomous worm capabilities, attempting to use the stolen npm and GitHub tokens to automatically publish malicious package updates to other downstream packages owned by the compromised developer or organization.
Obfuscation or Evasion
The router_init.js loader used complex multi-layered control-flow flattening, string encryption, and dead-code insertion to evade static analysis filters. Additionally, it attempted to download the Bun runtime (setup_bun.js) to execute its subsequent phases, circumventing Node-specific endpoint detection products.
Affected Assets and Blast Radius
affected_assets:
ecosystems:
- "npm"
packages:
- "@tanstack/zod-adapter"
- "@tanstack/router"
- "@tanstack/react-router"
- "@tanstack/react-query"
- "@tanstack/table-core"
versions:
- "1.166.12"
- "1.166.15"
repositories:
- "github.com/tanstack/router"
- "github.com/tanstack/query"
container_images: []
CI_CD_systems:
- "GitHub Actions"
developer_tools:
- "npm CLI"
- "VS Code"
environments:
- developer workstations
- CI runners
- build pipelines
credentials_at_risk:
- npm tokens
- GitHub tokens
- cloud credentials
- SSH keys
- environment variables
not_currently_known_to_affect:
- Production environments where install scripts are disabled (`--ignore-scripts`).
Indicators of Compromise
domains:
- value: git-tanstack[.]com
source: https://tanstack.com
confidence: high
ips: []
urls:
- value: hxxps://git-tanstack[.]com
source: https://tanstack.com
confidence: high
hashes:
- value: ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c
source: https://snyk.io
confidence: high
files:
- value: router_init.js
source: https://tanstack.com
confidence: high
- value: tanstack_runner.js
source: https://tanstack.com
confidence: high
package_versions:
- value: @tanstack/zod-adapter@1.166.12
source: https://tanstack.com
confidence: high
- value: @tanstack/zod-adapter@1.166.15
source: https://tanstack.com
confidence: high
Detection and Hunting
hunt_queries:
dependency_lockfiles:
- "@tanstack/zod-adapter@1.166.12"
- "@tanstack/zod-adapter@1.166.15"
files:
- "router_init.js"
- "tanstack_runner.js"
network:
- "git-tanstack[.]com"
ci_cd_checks:
- "Audit GitHub Actions workflow files for pull_request_target triggers paired with write permissions."
endpoint_checks:
- "Look for unexplained folders containing setup_bun.js or router_init.js."
Remediation Workflow
- Immediate: Isolate the affected host or development workstation. Inspect the environment for active persistence hooks (LaunchAgents, VS Code configuration files) before revoking secrets to prevent the triggering of the malware’s destructive dead man’s switch.
- Short-term: Terminate any running Python/Node processes associated with the compromise. Delete all local files named
router_init.jsandtanstack_runner.js. Once the system is clean, rotate all credentials stored on the host (GitHub PATs, AWS access keys, SSH keys, npmrc configurations). - Long-term: Mandate the use of the
--ignore-scriptsflag during npm installations on developer workstations and CI runners. Enforce strict branch protection rules and multi-admin approval for package registry publishing.
Defensive Lessons
- prevent: Restrict GitHub Actions token permissions by setting default permissions to
contents: readand locking down workflows that utilizepull_request_targettriggers. - detect: Implement registry scanning tools that inspect package release payloads for unexpected lifecycle scripts or abnormal repository reference injections.
- respond: Maintain a robust, isolated backup environment to restore compromised workstations and establish atomic secret-rotation runbooks.
Open Questions
- What was the total number of downloads of the malicious versions during the 55-minute exposure window?
- Did the malware successfully publish rogue versions of other downstream developer packages prior to key revocation?
Sources
- TanStack Official Postmortem. Role: DIRECT_SOURCE Impact: Detailed timeline, affected versions, and root cause analysis of the pipeline hijacking.
- GHSA-g7cv-rxg3-hmpx Advisory Record. Role: DIRECT_SOURCE Impact: Official vulnerability tracking and affected version mapping.
- Snyk Security Analysis of TanStack Incident. Role: PRIMARY_RESEARCH Impact: In-depth breakdown of the “Pwn Request” pattern and OIDC token hijacking vector.
- StepSecurity Incident Investigation Report. Role: PRIMARY_RESEARCH Impact: Detailed technical analysis of the runner cache poisoning and loader persistence mechanics.