A practical guide to understanding, detecting, and protecting against the largest npm supply chain attack of 2026. 170+ packages compromised — here's what every frontend developer and business owner needs to know.
In late April 2026, a new variant of the Shai-Hulud supply chain worm appeared in the npm ecosystem. Security researchers quickly dubbed it "Mini Shai-Hulud" — a self-propagating worm that spread through npm's trusted package infrastructure, compromising developer credentials and publishing malicious versions of legitimate packages.
The attack unfolded in two waves. The first wave (late April) targeted the
SAP developer ecosystem, compromising packages like @cap-js/sqlite,
@cap-js/postgres, and mbt. The second wave
(May 11–12) expanded dramatically: 373 malicious versions across 169 npm package names,
including 42 @tanstack/* packages, the entire @mistralai SDK
suite, @uipath automation tools, and packages in the @squawk
and @tallyui namespaces.
StepSecurity detected the May 11th attack within 30 minutes. All affected package versions have been deprecated on npm and now display SECURITY warnings. But for developers and organizations that installed these packages during the window of exposure, the damage could be extensive: stolen credentials, compromised CI/CD pipelines, and unauthorized package publishing.
170+ npm packages affected across the TanStack, Mistral AI, UiPath, Squawk, TallyUI, and SAP ecosystems. 404 malicious versions total. Credentials stolen include GitHub tokens, npm access tokens, AWS/Azure/GCP cloud keys, GitHub Actions secrets, and Kubernetes service account tokens.
Mini Shai-Hulud executes a multi-stage attack chain that begins the moment
a developer runs npm install. Understanding each stage helps you recognize the
attack patterns and protect your own projects.
The attackers modified the package.json of legitimate packages, adding a
preinstall script:
"scripts": {
"preinstall": "node setup.mjs"
}
npm executes preinstall hooks before the package installation
completes — meaning the malicious code runs automatically. The rest of the
package source remains identical to the clean version, making casual code review
ineffective. Only the install hook and two added files (setup.mjs and
execution.js) differ from the legitimate release.
The setup.mjs file is a small loader that downloads Bun v1.3.13 from GitHub
releases, extracts the binary, and uses Bun to execute the main payload. Using Bun is
strategic — it's a self-contained JavaScript runtime that doesn't depend on the local
Node.js installation, allowing the malware to execute in environments where Node is
constrained or unavailable.
The execution.js file contains a single large obfuscated payload using a custom
scrambler called ctf-scramble-v2. It checks for CI environments, avoids
Russian-locale machines, and daemonizes itself to keep running after install completes.
The credential stealer targets a wide range of high-value assets:
The GitHub Actions stealing path is sophisticated: an embedded Python helper scans
/proc for the Runner.Worker process, reads its memory, and
extracts masked secrets directly from the running CI worker — recovering secrets that
GitHub would otherwise scrub from job logs.
Mini Shai-Hulud uses GitHub itself as its exfiltration channel. After collecting credentials, it encrypts the results with AES-256-GCM (key wrapped by an embedded RSA public key) and commits the encrypted bundle to a public GitHub repository it creates using a stolen token. These repositories carry randomized Dune-themed names and the description "A Mini Shai-Hulud has Appeared".
The malware also scans GitHub commits for the keyword
OhNoWhatsGoingOnWithGitHub, treating commit messages with the format
OhNoWhatsGoingOnWithGitHub:<base64> as token dead-drops — decoding
the base64 value into a GitHub token for further propagation.
Once Mini Shai-Hulud has valid tokens, it automatically propagates: it identifies npm
packages the victim is authorized to publish, injects its payload into those packages,
increments the patch version, and publishes the compromised release. It also attempts
to push payload files into .vscode/ and .claude/ directories
using stolen GitHub Actions tokens, committing with the message
chore: update dependencies and the author claude.
The May 2026 wave introduced a more sophisticated entry path. Instead of an explicit preinstall hook, the malicious TanStack packages used an optional dependency pointing to a GitHub-hosted package:
"optionalDependencies": {
"@tanstack/setup": "github:tanstack/router#79ac49..."
}
The Git dependency contains a prepare script that runs the payload. The
trailing exit 1 causes npm to treat the optional dependency as failed —
making the install output look less suspicious while the payload has already executed.
If your project uses any package from these namespaces, check your lockfile immediately:
@tanstack/* @mistralai/* @uipath/* @squawk/* @tallyui/* @cap-js/* mbt
Here's a step-by-step checklist to verify your project's safety:
package-lock.json or yarn.lock for any package from the affected namespaces with publish dates around May 11–12, 2026.npm audit will flag deprecated versions with SECURITY warnings. Pay special attention to @tanstack/* and @mistralai/* packages.chore: update dependencies commits by the claude author, or any unusual package publishing activity..vscode/ (tasks.json, setup.mjs) or .claude/ (execution.js, setup.mjs) directories.Treat the developer machine or CI/CD runner as fully compromised. Immediately rotate: npm tokens, GitHub PATs, GitHub Actions secrets, and AWS/Azure/GCP cloud credentials. Audit all recent package publishing activity and CI/CD workflow executions for unauthorized access.
Supply chain attacks aren't going away. Here's a practical defense strategy that every development team should implement:
^ or ~ in production dependencies unless you control the packagenpm ci instead of npm install in CI/CD to enforce exact lockfile resolutionpackage-lock.json or yarn.lock in version controlnpm install --ignore-scripts first, audit the code, then run scripts manuallypreinstall script should trigger extra scrutinynpm audit regularly — Set up a pre-commit hook or CI step that runs npm audit --audit-level=highnpm audit in CI — Fail the build on high/critical advisories--ignore-scripts in CI, then selectively enable for trusted packagesIf you're hiring a web developer or agency to build your website, supply chain security is now part of the conversation. Mini Shai-Hulud shows that a single compromised dependency can expose your entire project — and potentially your infrastructure credentials — to attackers.
Here's what to look for in a developer or team:
The npm ecosystem is the backbone of modern frontend development. Trust in it is earned through vigilance — and that vigilance should be part of your developer's professional practice. When I build web applications for clients, dependency security and regular npm audits are baked into the development process from day one.
pull_request_target GitHub Action to steal a privileged GitHub token and download Grafana's entire private codebase. While the npm supply chain attack used install scripts as the vector, both incidents target the same thing: credentials accessible in build and deployment infrastructure. Together, they demonstrate that securing your GitHub tokens and CI/CD pipelines is inseparable from securing your dependency tree.Mini Shai-Hulud is a wake-up call for the entire frontend ecosystem. Supply chain attacks are not theoretical — they're happening now, and they're getting more sophisticated. The good news: the defense tools exist, and they're mostly free.
If you're building a web application and want a developer who treats security as a
first-class concern — not an afterthought — reach out to me.
I'm a full-stack developer with 20+ years of experience, and I build
every project with dependency security baked in from day one: npm audit in CI,
pinned versions, 2FA everywhere, and regular lockfile reviews.
Have a project in mind? I'll help you choose a secure, modern tech stack and build it right. Free initial consultation.