By falco365 · Published May 12, 2026

Mini Shai-Hulud May 2026: SLSA-signed malicious packages across TanStack, Mistral AI, Guardrails AI, UiPath, and OpenSearch

The May 11, 2026 Mini Shai-Hulud wave compromised 42 TanStack packages and spread to Mistral AI, Guardrails AI, UiPath, and OpenSearch — 373–416 malicious package-version entries across npm and PyPI. The attack produced valid SLSA Build Level 3 provenance attestations on malicious packages, bypassing the supply-chain defense that most organizations consider sufficient. The payload introduces two capabilities not seen in prior waves: Session P2P network exfiltration (no domain to block), and post-uninstall persistence via Claude Code hooks and VS Code auto-run tasks.

Mini Shai-Hulud May 2026: SLSA-signed malicious packages across TanStack, Mistral AI, Guardrails AI, UiPath, and OpenSearch
Analysis

On May 11, 2026, Mini Shai-Hulud — the self-propagating npm worm documented in the April 29 SAP CAP compromise — returned at scale. The attack began with TanStack, the widely-used React data-fetching library ecosystem, and spread to Mistral AI, Guardrails AI, UiPath, and OpenSearch using stolen CI/CD credentials. Aikido recorded 373 malicious package-version entries; Socket tracked 416 compromised artifacts across npm and PyPI; Endor Labs identified over 160 compromised npm packages.

Three capabilities distinguish this wave from all prior Mini Shai-Hulud activity:

  1. Valid SLSA Build Level 3 provenance attestations on malicious packages. The 84 malicious TanStack package versions carried genuine, unforgeable SLSA attestations — the packages were signed by npm's infrastructure and tied to the legitimate TanStack/router release workflow. From a developer's perspective, they appeared cryptographically authentic. This is the first confirmed supply-chain attack to bypass SLSA Level 3 provenance as a defense.
  2. Session P2P network exfiltration. Previous waves used GitHub dead-drop commits (api.github.com). This wave exfiltrates via the Session (formerly Loki) P2P messenger network. The traffic is encrypted messenger traffic with no central endpoint — standard domain blocklists and SIEM rules for suspicious GitHub API calls do not apply.
  3. Post-uninstall persistence. The payload writes itself into Claude Code hooks and VS Code auto-run tasks. Removing the malicious npm package does not remove the payload — it remains active on the developer's machine until explicitly hunted and deleted.
What we know
  • May 11, 2026 — StepSecurity's OSS Package Security Feed detected malicious versions in official @tanstack packages. The attack spread to additional projects using stolen credentials throughout the day.
  • Entry point: TanStack/router repository. The attacker exploited three chained vulnerabilities: (1) a pull_request_target workflow that ran in the context of the target repository, granting access to repository secrets on pull requests from forks; (2) GitHub Actions cache poisoning; (3) OIDC token theft from runner process memory.
  • Scale: 84 malicious versions across 42 TanStack packages (StepSecurity/TanStack post-mortem). Socket: 416 compromised artifacts. Aikido: 373 malicious package-version entries. Endor Labs: 160+ npm packages.
  • All victims share the same payload. SafeDep confirmed that compromised Mistral AI and TanStack packages drop identical credential-stealing payloads. This is a single worm, not parallel independent attacks.
  • Valid SLSA attestations: The malicious packages carried valid Sigstore attestations and GitHub Actions signatures tied to the legitimate TanStack/router Release workflow. Snyk noted this means "the attack produces valid SLSA Build Level 3 attestations for malicious packages."
The SLSA bypass: four-step analysis

This is the analytically significant finding. The community has treated SLSA Level 3 provenance as a strong supply-chain defense. This attack falsifies that assumption.

Observation: 84 malicious TanStack package versions carry valid SLSA Level 3 attestations, issued by npm's signing infrastructure, tied to the legitimate TanStack/router release workflow. The attestations are genuine — they were not forged. Multiple security vendors confirmed this independently.

Mechanism: SLSA Level 3 attestations prove WHERE a package was built — specifically, that it was built in the named CI/CD workflow. They do not prove that the build workflow was uncompromised at the time of the build. The attacker stole OIDC tokens from the pull_request_target workflow by running attacker-controlled code in the legitimate workflow context. The resulting packages were genuinely built by the TanStack/router Release workflow — with attacker-injected payloads included. The signing infrastructure signed what it was given.

Inference: SLSA Level 3 is a necessary but not sufficient supply-chain defense. It binds packages to build pipelines. It does not bind build pipelines to integrity. An attestation answers "was this package built by workflow X?" — it cannot answer "was workflow X clean when it built this?" A compromised pull_request_target workflow that runs in the privileged repository context can inject any payload and still receive a valid attestation.

Confidence bound: This inference is robust against alternative explanations. The only scenario where SLSA Level 3 would provide stronger protection is if the OIDC issuance were scoped to verified-clean workflow runs — a capability not present in current npm/GitHub OIDC integration. SLSA Level 4 (proposed, unreleased) includes builder integrity requirements that would partially address this by constraining which commits can trigger signing workflows.

The practical implication: organizations that have implemented SLSA Level 3 verification as a complete supply-chain defense need to revisit their threat model. SLSA Level 3 tells you the package came from the workflow it claims. It does not tell you the workflow was clean. Behavioral analysis at install time is required in addition to, not instead of, provenance verification.
TanStack entry chain: three vulnerabilities

The attack on TanStack was not a single vulnerability — it required chaining three weaknesses in the CI/CD configuration:

  1. pull_request_target workflow with access to repository secrets. GitHub's pull_request_target event was designed to allow PR workflows to have write access to the target repository, enabling actions like labeling PRs from forks. When a workflow using pull_request_target checks out PR code and runs it, that code executes with the target repository's secrets — including OIDC tokens. TanStack/router had such a workflow.

  2. GitHub Actions cache poisoning. The attacker poisoned a GitHub Actions cache entry to inject malicious code into subsequent workflow runs. Cache poisoning is a known attack class against GitHub Actions that enables persistent code injection without requiring ongoing access.

  3. OIDC token theft from runner memory. StepSecurity confirmed the payload reads GitHub Actions runner process memory to extract OIDC tokens — the same technique used in the April 29 SAP CAP compromise (where Runner.Worker memory was read to extract GitHub Actions secrets). With a valid OIDC token from a release workflow, the attacker could publish packages through npm's legitimate publishing path, receiving SLSA attestations from npm's signing infrastructure.

Endor Labs identified an additional delivery technique: an orphaned commit pushed to a fork of TanStack/router. Because GitHub's shared fork object storage makes commits accessible from any fork via the parent repository, this orphaned commit could be referenced as an optional dependency and fetched during npm install without appearing in any branch.

New capabilities in this wave

Session P2P exfiltration. Previous Mini Shai-Hulud waves exfiltrated credentials via GitHub dead-drop repositories (attacker-controlled public repos with randomized names). This wave uses the Session P2P network — an encrypted, decentralized messenger network with no central server. Exfil traffic appears as encrypted messenger communications. The C2 endpoints are *.getsession[.]org. There is no single domain to sinkhole, no GitHub API pattern to alert on, and no central repository to take down. This is a meaningful operational upgrade from the GitHub dead-drop pattern.

Post-uninstall persistence. The payload writes itself into:

  • Claude Code hooks — configuration files that Claude Code reads and executes on startup
  • VS Code auto-run tasks — tasks defined in .vscode/tasks.json that execute automatically when a workspace is opened

Both mechanisms survive npm uninstall of the malicious package. The payload is not in the package directory — it is in IDE configuration files that will be read and executed the next time the developer opens their IDE or runs Claude Code. Remediation requires explicitly hunting and deleting these files, not just updating the package.

Destructive routine. On hosts where the detected locale matches Israel or Iran, the payload has a 1-in-6 probability of executing rm -rf /. Microsoft Threat Intelligence confirmed this in analysis of the Mistral AI PyPI payload. This behavior parallels CanisterWorm's March 2026 destructive routine that targeted Kubernetes platforms matching Iran's timezone. The consistency across campaigns strengthens the inference of a shared codebase.

Mistral AI and PyPI branch

The Mistral AI compromise extended the worm to PyPI. Microsoft Threat Intelligence analyzed the payload delivered via a malicious @mistralai/mistralai version. The payload was named transformers.pyz — a deliberate impersonation of the Hugging Face Transformers library. Three @mistralai/mistralai versions were published in rapid succession on May 11: 2.2.2, 2.2.3, and 2.2.4 within an 8-minute window (22:45–22:53 UTC), consistent with the worm's automated publication cadence observed in the April 29 wave.

The PyPI branch uses the same credential-stealing payload (confirmed by SafeDep) but packages it as a Python zip archive rather than a JavaScript bundle. The geofencing logic is identical: Russian locale detected → exit; Israel/Iran detected → 1-in-6 destructive wipe.

Indicators of compromise

Compromised victims (partial — full lists at vendor sources):

  • 42 @tanstack/* npm packages — 84 malicious versions (TanStack post-mortem)
  • @mistralai/mistralai versions 2.2.2, 2.2.3, 2.2.4 (npm); PyPI packages pending full vendor list
  • Guardrails AI, UiPath, OpenSearch npm/PyPI packages — version details in vendor reports

Network indicators (defanged):

  • *.getsession[.]org — Session P2P exfil endpoints
  • api.masscan[.]cloud — C2 fallback endpoint
  • git-tanstack[.]com — typosquat staging domain

Filesystem persistence artifacts (survive npm uninstall):

  • Claude Code hooks directory — check ~/.claude/ and project-level .claude/ for unexpected hooks or modified settings.json
  • VS Code auto-run tasks — check .vscode/tasks.json for unexpected runOn: folderOpen tasks, especially those referencing setup.mjs, router_runtime.js, or Bun
  • setup.mjs and router_runtime.js in any path outside the expected package directory

Propagation artifacts:

  • OhNoWhatsGoingOnWithGitHub in GitHub commit messages (token dead-drop marker, carried from April wave)
  • GitHub repositories with description "A Mini Shai-Hulud has Appeared"

Payload naming (Mistral AI PyPI):

  • transformers.pyz — Python zip payload; impersonates Hugging Face Transformers library
Detection and mitigation
  • Scan for IDE persistence immediately — this is not optional. Check ~/.claude/, project-level .claude/, and all .vscode/tasks.json files for unexpected entries. The payload survives package removal; every compromised developer machine will still be running it until explicitly cleaned. Run: grep -r "setup.mjs\|router_runtime\|getsession" ~/.claude/ .vscode/ 2>/dev/null
  • Block all three C2 domains at DNS and proxy. *.getsession.org, api.masscan.cloud, git-tanstack.com — any connection to these from developer machines or CI/CD is active exfiltration in progress.
  • Treat SLSA Level 3 attestations as incomplete defense for this attack class. Package provenance confirms origin workflow; it does not confirm workflow integrity. Until SLSA Level 4 (or equivalent build environment integrity guarantees) are implemented, add behavioral analysis at install time: alert on preinstall hooks that download Bun, spawn detached processes, or make outbound connections during npm install.
  • Rotate all credentials from affected environments. Collection scope: GitHub Actions OIDC tokens, PATs, Git credentials, npm publish tokens, AWS (Secrets Manager, IAM, ESC task credentials), Kubernetes service accounts, HashiCorp Vault tokens, SSH keys, Claude Code configs, VS Code tasks, .env files.
  • Audit pull_request_target workflows in your repositories. Any workflow that checks out PR code and runs it in the pull_request_target context with access to repository secrets is vulnerable to this attack class. The fix is to isolate PR code checkout from secret-access workflows, or use ephemeral runners with no persistent credential access.
  • Enforce lockfile-only installs. npm ci (not npm install) prevents auto-resolution of new patch versions. This does not block intentionally published malicious versions, but it prevents silent adoption of worm-published versions outside your lockfile window.
  • Check GitHub audit logs for OhNoWhatsGoingOnWithGitHub. Token dead-drop marker consistent across all Mini Shai-Hulud waves. Any match means prior-wave credentials are circulating in the worm's token pool.
  • For compromised Mistral AI PyPI environments: Hunt for transformers.pyz in any Python environment that installed affected @mistralai/mistralai versions. This is the renamed Python payload — its presence confirms execution.
Attribution and cluster position

This is the largest Mini Shai-Hulud wave to date by artifact count (373–416 malicious entries vs. the April 29 SAP CAP wave's four packages). The payload is unchanged at its core — Bun v1.3.13, router_runtime.js, setup.mjs, Russian locale exit — confirming the same codebase as the prior waves. New capabilities (Session P2P exfil, IDE persistence, conditional destructive routine) represent operational upgrades to an existing toolkit, not a new actor.

The SLSA Level 3 bypass is the most significant tactical evolution. It means the attack is now invisible to one of the most widely-recommended supply-chain defenses. Defenders who verified SLSA attestations on the TanStack packages would have seen valid signatures from the legitimate workflow — and still installed the malicious payload.

See the npm supply-chain worm cluster analysis for the full cluster timeline, and Mini Shai-Hulud April 29 for the direct precursor event that established the worm's toolchain.

Criminal-market signal

No dark-web presence for Mini Shai-Hulud tooling or exfiltrated credentials has been observed. The operator-run credential-collection model confirmed across the entire TeamPCP/Mini Shai-Hulud cluster applies. The Session P2P exfil upgrade is consistent with an operator actively improving operational security — a commodity actor selling access would not invest in replacing GitHub dead-drop with a P2P network. The conditional destructive routine (Israel/Iran wipe) is not a criminal-market monetization; it is a geopolitically motivated destructive capability that further distinguishes this operator from financially motivated commodity actors. H2 operator-run pattern confirmed, with the destructive component as an additional indicator of non-commodity intent.