A new wave of the Mini Shai-Hulud campaign is drawing attention across the security community because it targets something modern software teams rely on every day: open-source packages and automated release pipelines.
This is not a traditional malware incident where users download an obviously suspicious file. Instead, the attack abuses trusted developer workflows, package managers, CI/CD systems, and publishing mechanisms. That makes it especially serious for engineering teams, security teams, and organizations that depend on JavaScript and Python ecosystems.
What is Mini Shai-Hulud?
Mini Shai-Hulud is a self-spreading supply-chain malware campaign targeting developer ecosystems.
In this latest wave, security researchers reported malicious package versions across npm and PyPI. The affected ecosystem included packages associated with well-known projects and vendors such as TanStack, UiPath, Mistral AI, Guardrails AI, and others.
The goal of the malware is not only to infect one machine. It is designed to steal credentials from developer environments and CI/CD systems, then use those credentials to publish more compromised packages.
That is what makes this different from a simple credential stealer. It tries to turn trusted software delivery systems into the next distribution path.
Packages
- @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
- @cap-js/db-service 2.10.1
- @cap-js/postgres 2.2.2
- @cap-js/sqlite 2.2.2
- @dirigible-ai/sdk 0.6.2, 0.6.3
- @draftauth/client 0.2.1, 0.2.2
- @draftauth/core 0.13.1, 0.13.2
- @draftlab/auth 0.24.1, 0.24.2
- @draftlab/auth-router 0.5.1, 0.5.2
- @draftlab/db 0.16.1, 0.16.2
- @mesadev/rest 0.28.3
- @mesadev/saguaro 0.4.22
- @mesadev/sdk 0.28.3
- @mistralai/mistralai 2.2.2, 2.2.3, 2.2.4
- @mistralai/mistralai-azure 1.7.1, 1.7.2, 1.7.3
- @mistralai/mistralai-gcp 1.7.1, 1.7.2, 1.7.3
- @ml-toolkit-ts/preprocessing 1.0.2, 1.0.3
- @ml-toolkit-ts/xgboost 1.0.3, 1.0.4
- @opensearch-project/opensearch 3.5.3, 3.6.2, 3.7.0, 3.8.0
- @squawk/airport-data 0.7.4, 0.7.5, 0.7.6, 0.7.7, 0.7.8
- @squawk/airports 0.6.2, 0.6.3, 0.6.4, 0.6.5, 0.6.6
- @squawk/airspace 0.8.1, 0.8.2, 0.8.3, 0.8.4, 0.8.5
- @squawk/airspace-data 0.5.3, 0.5.4, 0.5.5, 0.5.6, 0.5.7
- @squawk/airway-data 0.5.4, 0.5.5, 0.5.6, 0.5.7, 0.5.8
- @squawk/airways 0.4.2, 0.4.3, 0.4.4, 0.4.5, 0.4.6
- @squawk/fix-data 0.6.4, 0.6.5, 0.6.6, 0.6.7, 0.6.8
- @squawk/fixes 0.3.2, 0.3.3, 0.3.4, 0.3.5, 0.3.6
- @squawk/flight-math 0.5.4, 0.5.5, 0.5.6, 0.5.7, 0.5.8
- @squawk/flightplan 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5.6
- @squawk/geo 0.4.4, 0.4.5, 0.4.6, 0.4.7, 0.4.8
- @squawk/icao-registry 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5.6
- @squawk/icao-registry-data 0.8.4, 0.8.5, 0.8.6, 0.8.7, 0.8.8
- @squawk/mcp 0.9.1, 0.9.2, 0.9.3, 0.9.4, 0.9.5
- @squawk/navaid-data 0.6.4, 0.6.5, 0.6.6, 0.6.7, 0.6.8
- @squawk/navaids 0.4.2, 0.4.3, 0.4.4, 0.4.5, 0.4.6
- @squawk/notams 0.3.6, 0.3.7, 0.3.8, 0.3.9, 0.3.10
- @squawk/procedure-data 0.7.3, 0.7.4, 0.7.5, 0.7.6, 0.7.7
- @squawk/procedures 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5.6
- @squawk/types 0.8.1, 0.8.2, 0.8.3, 0.8.4, 0.8.5
- @squawk/units 0.4.3, 0.4.4, 0.4.5, 0.4.6, 0.4.7
- @squawk/weather 0.5.6, 0.5.7, 0.5.8, 0.5.9, 0.5.10
- @supersurkhet/cli 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7
- @supersurkhet/sdk 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7
- @tallyui/components 1.0.1, 1.0.2, 1.0.3
- @tallyui/connector-medusa 1.0.1, 1.0.2, 1.0.3
- @tallyui/connector-shopify 1.0.1, 1.0.2, 1.0.3
- @tallyui/connector-vendure 1.0.1, 1.0.2, 1.0.3
- @tallyui/connector-woocommerce 1.0.1, 1.0.2, 1.0.3
- @tallyui/core 0.2.1, 0.2.2, 0.2.3
- @tallyui/database 1.0.1, 1.0.2, 1.0.3
- @tallyui/pos 0.1.1, 0.1.2, 0.1.3
- @tallyui/storage-sqlite 0.2.1, 0.2.2, 0.2.3
- @tallyui/theme 0.2.1, 0.2.2, 0.2.3
- @tanstack/arktype-adapter 1.166.12, 1.166.15
- @tanstack/eslint-plugin-router 1.161.9, 1.161.12
- @tanstack/eslint-plugin-start 0.0.4, 0.0.7
- @tanstack/history 1.161.9, 1.161.12
- @tanstack/nitro-v2-vite-plugin 1.154.12, 1.154.15
- @tanstack/react-router 1.169.5, 1.169.8
- @tanstack/react-router-devtools 1.166.16, 1.166.19
- @tanstack/react-router-ssr-query 1.166.15, 1.166.18
- @tanstack/react-start 1.167.68, 1.167.71
- @tanstack/react-start-client 1.166.51, 1.166.54
- @tanstack/react-start-rsc 0.0.47, 0.0.50
- @tanstack/react-start-server 1.166.55, 1.166.58
- @tanstack/router-cli 1.166.46, 1.166.49
- @tanstack/router-core 1.169.5, 1.169.8
- @tanstack/router-devtools 1.166.16, 1.166.19
- @tanstack/router-devtools-core 1.167.6, 1.167.9
- @tanstack/router-generator 1.166.45, 1.166.48
- @tanstack/router-plugin 1.167.38, 1.167.41
- @tanstack/router-ssr-query-core 1.168.3, 1.168.6
- @tanstack/router-utils 1.161.11, 1.161.14
- @tanstack/router-vite-plugin 1.166.53, 1.166.56
- @tanstack/solid-router 1.169.5, 1.169.8
- @tanstack/solid-router-devtools 1.166.16, 1.166.19
- @tanstack/solid-router-ssr-query 1.166.15, 1.166.18
- @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/start-client-core 1.168.5, 1.168.8
- @tanstack/start-fn-stubs 1.161.9, 1.161.12
- @tanstack/start-plugin-core 1.169.23, 1.169.26
- @tanstack/start-server-core 1.167.33, 1.167.36
- @tanstack/start-static-server-functions 1.166.44, 1.166.47
- @tanstack/start-storage-context 1.166.38, 1.166.41
- @tanstack/valibot-adapter 1.166.12, 1.166.15
- @tanstack/virtual-file-routes 1.161.10, 1.161.13
- @tanstack/vue-router 1.169.5, 1.169.8
- @tanstack/vue-router-devtools 1.166.16, 1.166.19
- @tanstack/vue-router-ssr-query 1.166.15, 1.166.18
- @tanstack/vue-start 1.167.61, 1.167.64
- @tanstack/vue-start-client 1.166.46, 1.166.49
- @tanstack/vue-start-server 1.166.50, 1.166.53
- @tanstack/zod-adapter 1.166.12, 1.166.15
- @taskflow-corp/cli 0.1.24, 0.1.25, 0.1.26, 0.1.27, 0.1.28, 0.1.29
- @tolka/cli 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6
- @uipath/access-policy-sdk 0.3.1
- @uipath/access-policy-tool 0.3.1
- @uipath/admin-tool 0.1.1
- @uipath/agent-sdk 1.0.2
- @uipath/agent-tool 1.0.1
- @uipath/agent.sdk 0.0.18
- @uipath/aops-policy-tool 0.3.1
- @uipath/ap-chat 1.5.7
- @uipath/api-workflow-tool 1.0.1
- @uipath/apollo-core 5.9.2
- @uipath/apollo-react 4.24.5
- @uipath/apollo-wind 2.16.2
- @uipath/auth 1.0.1
- @uipath/case-tool 1.0.1
- @uipath/cli 1.0.1
- @uipath/codedagent-tool 1.0.1
- @uipath/codedagents-tool 0.1.12
- @uipath/codedapp-tool 1.0.1
- @uipath/common 1.0.1
- @uipath/context-grounding-tool 0.1.1
- @uipath/data-fabric-tool 1.0.2
- @uipath/docsai-tool 1.0.1
- @uipath/filesystem 1.0.1
- @uipath/flow-tool 1.0.2
- @uipath/functions-tool 1.0.1
- @uipath/gov-tool 0.3.1
- @uipath/identity-tool 0.1.1
- @uipath/insights-sdk 1.0.1
- @uipath/insights-tool 1.0.1
- @uipath/integrationservice-sdk 1.0.2
- @uipath/integrationservice-tool 1.0.2
- @uipath/llmgw-tool 1.0.1
- @uipath/maestro-sdk 1.0.1
- @uipath/maestro-tool 1.0.1
- @uipath/orchestrator-tool 1.0.1
- @uipath/packager-tool-apiworkflow 0.0.19
- @uipath/packager-tool-bpmn 0.0.9
- @uipath/packager-tool-case 0.0.9
- @uipath/packager-tool-connector 0.0.19
- @uipath/packager-tool-flow 0.0.19
- @uipath/packager-tool-functions 0.1.1
- @uipath/packager-tool-webapp 1.0.6
- @uipath/packager-tool-workflowcompiler 0.0.16
- @uipath/packager-tool-workflowcompiler-browser 0.0.34
- @uipath/platform-tool 1.0.1
- @uipath/project-packager 1.1.16
- @uipath/resource-tool 1.0.1
- @uipath/resourcecatalog-tool 0.1.1
- @uipath/resources-tool 0.1.11
- @uipath/robot 1.3.4
- @uipath/rpa-legacy-tool 1.0.1
- @uipath/rpa-tool 0.9.5
- @uipath/solution-packager 0.0.35
- @uipath/solution-tool 1.0.1
- @uipath/solutionpackager-sdk 1.0.11
- @uipath/solutionpackager-tool-core 0.0.34
- @uipath/tasks-tool 1.0.1
- @uipath/telemetry 0.0.7
- @uipath/test-manager-tool 1.0.2
- @uipath/tool-workflowcompiler 0.0.12
- @uipath/traces-tool 1.0.1
- @uipath/ui-widgets-multi-file-upload 1.0.1
- @uipath/uipath-python-bridge 1.0.1
- @uipath/vertical-solutions-tool 1.0.1
- @uipath/vss 0.1.6
- @uipath/widget.sdk 1.2.3
- agentwork-cli 0.1.4, 0.1.5
- cmux-agent-mcp 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8
- cross-stitch 1.1.3, 1.1.4, 1.1.5, 1.1.6, 1.1.7
- git-branch-selector 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7
- git-git-git 1.0.8, 1.0.9, 1.0.10, 1.0.11, 1.0.12
- guardrails-ai 0.10.1
- intercom-client 7.0.4
- lightning 2.6.2, 2.6.3
- mbt 1.2.48
- mistralai 2.4.6
- ml-toolkit-ts 1.0.4, 1.0.5
- nextmove-mcp 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7
- safe-action 0.8.3, 0.8.4
- ts-dna 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.0.5
- wot-api 0.8.1, 0.8.2, 0.8.3, 0.8.4
Why This Incident Matters
Modern software development depends heavily on package managers. A typical application may include hundreds or thousands of direct and transitive dependencies. Developers often install packages automatically, and CI systems often rebuild projects many times a day.
That creates a powerful attack surface.
If a malicious package runs during installation, it may execute in places where sensitive credentials are available, including:
- Developer laptops
- CI/CD runners
- Release workflows
- Internal build systems
- Container build environments
- Package publishing pipelines
These environments often have access to npm tokens, GitHub tokens, cloud credentials, deployment secrets, Kubernetes tokens, and other sensitive material.
In plain terms: this campaign is dangerous because it targets the places where software is built and shipped.
What Happened?
Researchers reported that attackers compromised a large number of package versions across popular developer ecosystems.
The npm side of the campaign affected multiple package groups, including packages connected to TanStack, UiPath, Mistral AI, Squawk, TallyUI, and others. Some reporting also noted related malicious activity in PyPI packages.
The most important part is not just the number of packages. It is how the attack spread.
Instead of relying only on stolen long-lived publishing tokens, parts of the campaign abused trusted release workflows and automated publishing paths. In some cases, malicious packages appeared to come from legitimate publishing infrastructure.
That makes detection harder, because defenders cannot simply ask "Did this package come from the expected maintainer?" Sometimes the answer may be yes, while the package is still malicious.
How the Attack Works
At a high level, the attack follows a familiar but dangerous pattern:
- A compromised package version is published.
- A developer or CI system installs that package.
- Install-time code executes automatically.
- The malware searches the environment for credentials and secrets.
- If useful credentials are found, the malware attempts to use them to spread further.
- Additional packages or releases may be compromised through trusted publishing paths.
The campaign used package lifecycle behavior to its advantage. Package managers often allow scripts to run during install, build, or prepare steps. These scripts are useful for legitimate projects, but attackers can abuse them to execute code before the developer realizes anything is wrong.
In this case, researchers described multiple delivery paths, including malicious files embedded in package archives and install-time scripts that executed additional payloads.
Why Trusted Publishing Is Not a Complete Safety Signal
One of the most important lessons from this incident is that trusted publishing does not automatically mean a package is safe.
Trusted publishing is designed to reduce the need for long-lived package registry tokens. For example, a GitHub Actions workflow can use identity-based authentication to publish a package. This is generally a good security improvement.
But there is a catch.
If an attacker can run code inside the release workflow, they may be able to abuse the workflow's own identity. That means a malicious release can still appear to come from the expected pipeline.
This does not mean trusted publishing is bad. It means trusted publishing answers only one question: where did the package come from? It does not prove that the build environment was clean.
Why CI/CD Systems Are Such Valuable Targets
CI/CD systems are attractive to attackers because they often sit at the center of software delivery.
A build runner may have access to:
- Source code
- Package publishing permissions
- Deployment credentials
- Cloud accounts
- Container registries
- Signing keys
- Internal services
- Secrets used by tests and release jobs
If malware runs in that environment, the impact can go far beyond a single developer machine.
This is why supply-chain attacks are so serious. They can move from one package to one build system, then from that build system into other packages, releases, or infrastructure.
What Makes This Campaign Different
Many dependency attacks are limited to one package or one maintainer account. This campaign is more concerning because it has worm-like behavior.
That means it attempts to spread itself by abusing the access it finds.
A normal malicious package might steal data and stop there. A worm-like supply-chain attack tries to keep moving. It looks for credentials that allow it to publish, modify, or influence other packages.
That creates a wider blast radius and makes the incident harder to contain.
What Are the Risks for Organizations?
The biggest risks are credential theft, unauthorized package publishing, and compromise of build or release systems.
For an organization, the consequences may include:
- Stolen source code or internal secrets
- Unauthorized access to cloud infrastructure
- Malicious releases published under trusted package names
- Compromised developer machines
- Poisoned build caches
- Exposed deployment credentials
- Loss of trust in recent package releases
- Downstream impact on customers or users
Even if an affected package was only installed temporarily, that may be enough for the malware to execute.
Does This Only Affect Production Systems?
No.
In many cases, developer and CI environments are more exposed than production systems.
A dependency may never make it into a production container, but it can still run during:
- Local development
- Dependency installation
- Testing
- Linting
- Builds
- Release preparation
- Package publishing
That means teams should not only ask "Did this reach production?" They should also ask "Did this run anywhere that had secrets?"
What Should Developers and Security Teams Do?
The first step is to identify whether any affected package versions were installed or executed in your environment.
Security teams should review:
- Lockfiles and package manager caches
- CI/CD logs and build artifacts
- Developer machines
- Recent package publishing activity
- Release workflow history
- Dependency update pull requests
- Unusual build failures
- Unexpected install-time script execution
If there is evidence that a malicious package ran, treat the environment as potentially exposed.
Rotate Secrets Carefully
Credential rotation is important, but it should be done thoughtfully.
If malware may have installed persistence on a developer machine, immediately revoking certain tokens could trigger destructive behavior in some variants. The safer approach is to first inspect and isolate suspicious systems, remove persistence if present, and then rotate credentials.
Teams should review and rotate:
- Package registry tokens
- GitHub personal access tokens and Actions secrets
- Cloud credentials and container registry credentials
- Deployment keys and Kubernetes service account tokens
- Vault or secret manager tokens
- Signing or release credentials
The exact scope depends on where the package ran and what secrets were available in that environment.
Review Recent Publishing Activity
Because this campaign can abuse release workflows, teams should audit recent package publishing activity.
Look for:
- Unexpected releases or version bumps that were not planned
- Releases published outside normal windows
- Unfamiliar workflow runs or unusual cache usage
- Changes to package contents that do not match source code
- New or modified lifecycle scripts
- Unexpected dependencies added shortly before release
This is especially important for maintainers of public packages.
Reduce Future Exposure
This incident is a reminder that package installation should not be treated as harmless. Useful hardening steps:
1. Limit secrets in build environments. CI jobs should only receive the secrets they actually need. A test job should not have publishing credentials unless it is truly publishing.
2. Separate build and release permissions. Do not allow every workflow to publish packages. Publishing should be limited to tightly controlled release workflows.
3. Be careful with install scripts. Lifecycle scripts are powerful. Consider disabling them where possible, especially in CI jobs that do not need them.
4. Pin dependencies and review lockfile changes. Lockfiles help teams understand exactly what was installed. Treat unexpected lockfile changes as security-relevant.
5. Protect CI caches. Build caches can improve speed, but they can also preserve malicious artifacts. Cache keys, restore behavior, and cache poisoning risks should be reviewed.
6. Monitor package contents, not just package names. A trusted package name is not enough. Security checks should inspect package contents, scripts, and unexpected files.
7. Use least privilege for publishing. Publishing permissions should be scoped, short-lived where possible, and monitored closely.
Final Thoughts
Mini Shai-Hulud is a strong reminder that the software supply chain is now one of the most valuable targets for attackers.
The most concerning part of this campaign is not only that popular packages were compromised. It is that the attack abused the trust developers place in package managers, release workflows, and automated publishing systems.
Trusted publishing, provenance, and CI automation are useful security improvements, but they are not magic shields. If the workflow itself is compromised, the release can still look legitimate from the outside.
For developers and security teams, the lesson is clear: dependency installation is code execution, CI/CD environments are high-value targets, and recent package releases should be treated with care when a supply-chain campaign is active.
If your environment installed affected package versions, assume secrets may have been exposed until proven otherwise. Review where the package ran, rotate credentials, inspect release workflows, and audit recent publishing activity.
Supply-chain security is no longer just about checking for vulnerable libraries. It is about understanding how software is built, who can publish it, and what happens when trust in that pipeline is abused.
Sources: - Wiz: Mini Shai-Hulud Strikes Again — TanStack + more npm Packages Compromised - Aikido: Mini Shai-Hulud Is Back — npm Worm Hits over 160 Packages, including Mistral and Tanstack - Snyk: TanStack npm Packages Hit by Mini Shai-Hulud - StepSecurity: TeamPCP's Mini Shai-Hulud Is Back - The Hacker News: Mini Shai-Hulud Worm Compromises TanStack, Mistral AI and More
