18/05/2026

SIGNED, ATTESTED, MALICIOUS :: How TanStack, Mistral and UiPath Got Owned Without a Stolen Credential

SIGNED, ATTESTED, MALICIOUS :: How TanStack, Mistral and UiPath Got Owned Without a Stolen Credential

supply-chainnpmgithub-actionsoidcteampcp

On May 11, 2026, TeamPCP shipped wave four of the Mini Shai-Hulud worm. 42 npm packages compromised. 84 artifacts. The TanStack router family was the initial vector. Mistral, UiPath, OpenSearch and others followed within hours. The blast radius is still being mapped at the time of writing.

The interesting part of this attack is not the payload. The payload is the same credential-stealing worm we have seen in three previous waves. The interesting part is how the malicious versions got published. Spoiler: no npm credentials were stolen. No maintainer accounts were phished. The attacker did not bypass MFA. They did not need to.

The chain

Three vulnerabilities in GitHub Actions were chained. None of them on their own would have been sufficient.

Step one — the attacker forked the TanStack/router repository. The fork was renamed zblgg/configuration. This is not standard hygiene. Forks of TanStack/router are visible from the upstream repo's "Network" view. By renaming the fork to something innocuous-looking, the attacker evaded any defender who was watching for forks of the project's name.

Step two — the attacker opened a pull request from the renamed fork. The PR triggered a pull_request_target workflow on TanStack/router. pull_request_target is the GitHub Actions trigger that runs in the context of the base repository — with access to its secrets — but checks out code from the fork. This is a well-documented foot-gun. GitHub themselves warns about it. The workflow on TanStack/router executed attacker-controlled code with the privileges of the upstream repository.

Step three — the attacker-controlled workflow poisoned the GitHub Actions cache. It dropped a malicious pnpm store into the cache. When a legitimate maintainer later merged a legitimate PR to main and the release workflow ran, the release workflow restored that cache. Now the release workflow was building with attacker-supplied dependencies.

Step four — the attacker-controlled binaries pulled inside the build read the GitHub Actions OIDC token directly from /proc/<pid>/mem. With that OIDC token, the build environment had the authority to publish to npm via trusted publishing.

The malicious package versions were published by the legitimate workflow, running on the legitimate branch, in the legitimate repository, with a legitimate OIDC token. The Sigstore attestations are valid. The SLSA provenance is valid. The packages are malware.

What the provenance actually attested

This is the part the supply-chain security industry needs to internalize.

SLSA provenance attests that a package was built by a specific GitHub Actions workflow in a specific repository on a specific ref. That is true of the TanStack packages. The provenance correctly states: built by release.yml on refs/heads/main in TanStack/router.

SLSA provenance does not attest:

  • That the workflow was authorized to run for this purpose
  • That the commit triggering the workflow originated from a protected source
  • That the build inputs — including caches — were untampered
  • That the workflow code itself had not been modified upstream of the build

The TanStack attack exploited the gap between what provenance claims and what defenders assume it claims. Defenders read "built by upstream's release workflow" and infer "safe." Provenance never made the second claim.

The npm trusted publishing fix

npm's trusted publishing supports two configuration levels. The loose configuration ties a package to a repository:

Trusted publisher:
  Repository: tanstack/router

The strict configuration ties a package to a specific repository, a specific workflow file, and a specific branch:

Trusted publisher:
  Repository: tanstack/router
  Workflow: .github/workflows/release.yml
  Branch: refs/heads/main

Any package using OIDC trusted publishing without branch and workflow pinning is vulnerable to this exact class of attack. The attacker only needs to find one workflow on the repository that can be made to run with privileged context — any workflow at all — and they can publish from it.

If your organization publishes packages via OIDC, audit every trusted publisher config today. Pin workflow and branch.

What this means for defenders

The takeaway is not "Sigstore is broken." Sigstore is doing exactly what it claims to do. The takeaway is that a signature is a claim, not a verdict.

A signed package tells you a build happened in a specific place. It tells you nothing about whether that build was legitimate. Treat signatures as one input to a trust decision, not the trust decision itself.

Defense in depth for this attack class:

  • Pin trusted publishers to branch and workflow, always
  • Disable pull_request_target workflows unless absolutely necessary; if necessary, do not check out untrusted code
  • Disable GitHub Actions cache for release workflows entirely, or scope cache to non-release workflows
  • Run release builds in ephemeral, network-restricted environments
  • Monitor for unexpected publishing events; the publish itself is the only ground truth
  • Pin all transitive dependencies in lockfiles; review lockfile diffs in PRs

This wave will not be the last. The same crew shipped four waves between September 2025 and May 2026. They are iterating. Wave five will exploit something else nobody has thought to defend.

The boring controls are the ones that survive each iteration. Boring is the strategy.

PROVENANCE THEATRE :: Signed Is Not Safe and SLSA Was Never the Whole Answer

PROVENANCE THEATRE :: Signed Is Not Safe and SLSA Was Never the Whole Answer slsa sigstore provenance supply-chain trust-model The su...