Research · Incident

Mini Shai-Hulud shows supply chain attacks now want your developer tokens

Last reviewed:

The current TanStack and Mini Shai-Hulud wave is less about poisoned packages and more about stealing the developer tokens that let attackers publish the next wave.

The current supply chain wave is not a story about one bad npm package. TanStack, Mistral AI, Guardrails AI, UiPath, OpenSearch, Grafana, GitHub and developer workstations all appear in the recent reporting, but the useful pattern is simpler: attackers are using trusted developer systems to steal the credentials that let them publish more trusted software.

StepSecurity attributes the TanStack wave to TeamPCP, the group it also links to earlier Mini Shai-Hulud activity. TanStack's own postmortem narrows the initial incident: on 11 May 2026, an attacker published 84 malicious versions across 42 @tanstack/* npm packages. TanStack says the attack combined a pull_request_target pattern, GitHub Actions cache poisoning across the fork and base trust boundary, and runtime extraction of an OIDC token from the Actions runner process. The npm publish workflow was not directly compromised. No npm token had to be stolen.

That last point is the reason this incident matters beyond JavaScript teams. The malware did not need to break the registry. It rode through the release path that defenders would normally trust.

Who is behind the current wave

Public attribution is not uniform across every write-up, so treat the labels carefully. StepSecurity names TeamPCP as the group behind the current Mini Shai-Hulud wave. Snyk repeats that attribution and connects it to previous TeamPCP compromises of developer tooling. The Hacker News, citing reports from several research teams, also names TeamPCP and describes the campaign as a fresh Mini Shai-Hulud operation.

The affected names are easier to verify than the actor label. TanStack has a first-party postmortem and GitHub advisory for the Router and Start package compromise. Wiz lists TanStack, UiPath, Mistral AI, Guardrails AI and OpenSearch-related packages among affected ecosystems, with a note that some variants had payload bugs. NHS England Digital issued a cyber alert naming npm and PyPI packages including @tanstack/react-router, @mistralai/mistralai, @opensearch-project/opensearch, @uipath/robot, mistralai==2.4.6 and guardrails-ai==0.10.1.

Separate reporting then links the same developer-supply-chain pressure to downstream organisational incidents. Infosecurity Magazine reports that GitHub confirmed unauthorised access to 3,800 internal repositories after a poisoned Nx Console VS Code extension landed on an employee device. Its report says Nx traced the credential theft path back to the broader TanStack supply-chain compromise. A13E Intel also tracked Grafana as a follow-on case where missed token rotation after TanStack exposure changed the response question from package clean-up to repository and credential review.

The short version: the attacker label is TeamPCP in the strongest public attribution I have seen, but the defensive lesson does not depend on perfect attribution. The campaign behaves like an identity attack running through software distribution.

How the attack works

The TanStack compromise is a good case study because it breaks the comforting mental model many teams still use for package security.

The old model says a package is dangerous when an attacker gets a maintainer password, steals an npm token, or uploads a lookalike package. Those still happen. This wave is nastier because the malicious versions were published through the legitimate pipeline. TanStack says the attacker poisoned the GitHub Actions cache from a workflow path exposed to pull-request code. A later release workflow restored that poisoned cache. Attacker-controlled code then extracted an OIDC token from runner memory and used the trusted-publisher path to create package versions with a valid release identity.

Snyk describes this as the first documented case of a malicious npm package carrying valid SLSA provenance. That is uncomfortable, but it is not a failure of provenance as a concept. Provenance can prove that a package came from the expected build process. It cannot prove that the build process was clean at runtime. If the runner is already poisoned, the attestation may be honestly describing a bad build.

The payload behaviour is also worth separating from the publication trick. TanStack and the GitHub advisory describe a large obfuscated JavaScript payload that runs during install. It looks for AWS, GCP, Kubernetes, Vault, npm, GitHub and SSH credentials in common locations. It also tries to enumerate packages maintained by the victim and republish infected versions. That is why this is a worm rather than a single malicious-package event.

StepSecurity's analysis adds persistence and exfiltration details: process-memory reads on GitHub Actions runners, credential collection from many local paths, persistence hooks in developer tools, and exfiltration through channels that may not look like classic malware infrastructure. The exact indicators will keep moving. The stable behaviour is credential access followed by propagation.

Why organisations keep getting caught

Most organisations have better production controls than developer controls. Production has IAM review, network policy, alerting, incident procedures and change gates. Developer laptops, CI runners, build caches, package-manager mirrors, IDE extensions and personal access tokens often sit in a softer zone because they belong to engineering rather than security operations.

That split no longer works. A CI runner can mint cloud credentials. A GitHub token can read private repositories, alter workflows, publish packages, rotate secrets or open the door to later phishing. A maintainer machine can hold npm tokens, SSH keys, cloud profiles, 1Password sessions, registry credentials, Docker credentials and repository remotes. A VS Code extension can reach both the filesystem and the developer's daily identity stack.

The GitHub and Nx Console reporting is the clearest example. The extension was reportedly available for a short window, but auto-update and developer trust can make a short window enough. Once the extension ran on a machine with useful credentials, the incident became a repository-access problem, not an extension problem.

There is a second trap: teams stop at dependency clean-up. Removing a bad package version is necessary, but it is not response. If an install script already ran on a developer machine or CI runner, the attacker may already have the tokens they wanted. The blast radius lives in audit logs, package-publishing records, GitHub Apps, deploy keys, cloud activity and unusual repository access.

That is why this campaign maps cleanly to T1195.001, Compromise Software Dependencies and Development Tools, but it also needs token-focused hunting under T1528, Steal Application Access Token and credential-file review under T1552.001, Credentials In Files. Treating it as only a package problem misses the path that lets the next package get poisoned.

What to do now

Start with exposure, not panic. Build a list of hosts and pipelines that installed affected packages in the relevant windows. For TanStack, TanStack's advisory names 11 May 2026 and the affected @tanstack/* package versions. NHS England Digital and Socket-linked lists cover the broader npm and PyPI set. Do not rely on one package list if you have both JavaScript and Python build paths.

Check lockfiles first. Search package-lock.json, pnpm-lock.yaml, yarn.lock, requirements.txt, poetry.lock, CI cache metadata, package-manager mirrors and artefact repositories for the affected package names and versions. Then map each hit to a host or runner. A lockfile hit on a developer laptop is a different response from a hit inside a privileged release workflow.

For any host where an affected install or import may have run, rotate credentials by reachability rather than proof of theft. Rotate GitHub personal access tokens, fine-grained tokens, npm tokens, PyPI tokens, cloud access keys, SSH deploy keys, CI secrets, Vault tokens, Kubernetes service accounts and password-manager CLI sessions reachable from that process. If the host held production deploy credentials, treat it as a production incident even if the trigger was an npm install.

Review GitHub and registry audit logs for the boring things attackers need to do: new package versions, unusual publish times, new workflow files, cache changes, GitHub Actions permission changes, package ownership changes, new repository collaborators, new deploy keys, secret reads, unusual clones, repository visibility changes and branch-protection edits. Do the same in cloud audit logs for the affected identities. Look for activity after the install window, not just during it.

Harden the release path after containment. Stop privileged workflows from running untrusted pull-request code. Review every use of pull_request_target; most repositories do not need it. Scope OIDC trusted publishing to protected branches and specific workflow files where the registry allows that shape. Cut default GITHUB_TOKEN permissions to read-only and grant write permissions per job. Treat GitHub Actions cache as a trust boundary, not a harmless speed feature. If a job accepts code from a fork, it should not write cache entries later consumed by release jobs.

Review developer-tooling trust. Pin VS Code extensions for staff who touch release systems. Disable extension auto-update where the operational cost is acceptable. Keep a known-good extension allowlist for build, release and security engineers. Collect extension inventory from managed endpoints and alert when a verified-publisher extension changes publisher, install source or version unexpectedly.

Finally, rehearse the uncomfortable sequence. A maintainer installs a poisoned package. The package steals a token. The token publishes another package. A downstream CI runner installs it. That runner holds cloud credentials. If your incident plan cannot follow that chain across endpoint, GitHub, registry, CI and cloud logs, it will fail in the middle.

What not to overstate

This is not evidence that every npm, PyPI or VS Code environment is compromised. TanStack says every currently available TanStack package version is safe to install after its clean-up. Wiz also notes that some affected package variants appear to have had non-functional payloads. Those details matter. Overstating the incident will make engineering teams tune out the next alert.

The sober conclusion is still sharp enough: modern supply chain attacks are becoming identity attacks with a package manager attached. The package is the delivery path. The prize is the token that lets the attacker become a publisher, a developer, a CI job or a cloud principal for the next hop. Defenders who only remove the package will keep losing to attackers who came for the credentials.

01 ATT&CK references