In the eight days between 11 May and 19 May 2026, a self-propagating npm worm that the security community has settled on calling Mini Shai-Hulud ran two waves through the JavaScript ecosystem. The first wave, on May 11, compromised 84 versions across 42 @tanstack packages and reached, among others, two employee devices at OpenAI. The second, on May 19, sprayed 639 malicious versions across 323 packages in the @antv data-visualisation ecosystem in roughly 27 minutes.
OpenAI confirmed on May 13 that the attackers had stolen its code-signing certificates for macOS, Windows, iOS, and Android applications, plus access to a limited set of internal source-code repositories. GitHub disclosed a few days later that the same campaign, via a hijacked Nx VS Code extension, had exfiltrated data from approximately 3,800 internal GitHub repositories.
These facts have been well covered. What has not been well covered — and what matters more for anyone running CI/CD pipelines in 2026 — is the technique. For the first publicly documented time, a worm propagated with valid Sigstore provenance and SLSA Build Level 3 attestations on every package it published. The system that the open-source ecosystem spent five years building as its last automated trust signal was not bypassed. It was used as camouflage.
This is a defender-focused read. No vendor pitch is attached.
- In May 2026, a self-spreading worm called Mini Shai-Hulud ran through the npm package ecosystem — the place where JavaScript developers download building blocks for their software.
- It compromised OpenAI (whose code-signing certificates for macOS, Windows, iOS, and Android apps were stolen), the Nx Console VS Code extension (≈6,000 silent auto-updates in 36 minutes), and the @antv visualisation libraries (323 packages poisoned in 27 minutes).
- The novel part: every malicious package carried a valid cryptographic "this came from a legitimate build" stamp (Sigstore provenance with SLSA Level 3 attestation). The security checks designed to catch fakes passed cleanly, because the worm produced them from inside the real maintainers' real build pipelines.
- Translation for non-technical readers: the lock wasn't picked. The attacker stole the key from the owner's pocket, walked through the front door, and the alarm system correctly confirmed: yes, the owner is home.
- The payload harvested everything sensitive a developer keeps on a laptop or in a build server: AWS keys, GitHub tokens, npm tokens, Kubernetes credentials, SSH keys, 1Password sessions, and — distinctively — Claude Code AI-assistant configuration files.
- The fix is not one product. It is a layered set of controls (cooldowns, ignore-scripts in CI, egress allow-lists, hardware-backed signing, AI-config hygiene) plus a hard truth: Sigstore provenance is now forensics, not a real-time gate.
A short history of how we got here
Mini Shai-Hulud did not appear in a vacuum. It is the latest point on a ten-year curve in which software supply-chain attacks have escalated from one-off curiosities to weekly events, and from cryptocurrency-stealing payloads to credential-harvesting worms that target the build infrastructure itself. The table below lists incidents we could verify against a primary source (vendor postmortem, official advisory, or CERT alert). Press-only coverage was excluded. Everything in this table is traceable; if a widely-cited "fact" did not survive verification, it does not appear here.
| Date | Package(s) / target | Technique | Verified impact | Primary source |
|---|---|---|---|---|
| 2016-03-22 | left-pad (npm) | Unpublication, not an attack | ~2-hour build-failure wave across dependent projects | npm blog |
| 2018-05-02 | getcookies / http-fetch-cookies / express-cookies (npm) | Maintainer account takeover, backdoor in dependency chain | Backdoor in mailparser chain (~64k weekly downloads); unpublished before known active exploitation | npm blog |
| 2018-07-12 | eslint-scope 3.7.2, eslint-config-eslint 5.0.2 | Maintainer credential compromise (password reuse) | Postinstall script exfiltrated .npmrc credentials; active for 2h 48m | ESLint postmortem |
| 2018-11-26 | event-stream → flatmap-stream (npm) | Social-engineered maintainer handoff, then malicious dependency added | Targeted Copay Bitcoin wallet users; undetected for ~7 weeks; ~8M downloads of flatmap-stream before removal | Snyk postmortem |
| 2019-03-26 | bootstrap-sass 3.2.0.3 (RubyGems) | Maintainer account compromise | RCE backdoor on Rails servers; ~1,477 downloads before removal | Sophos |
| 2020-03 → 2020-12 | SolarWinds Orion | Build pipeline compromise, signed with legitimate cert | ~18,000 customers received trojanised updates; nation-state attribution | CISA ED 21-01 |
| 2021-02-09 | (research disclosure) | Dependency confusion across npm / PyPI / RubyGems | Apple, Microsoft, PayPal, Netflix and 30+ others affected; $130k+ bounties | Alex Birsan |
| 2021-03-28 | php-src (git.php.net) | Source repository server compromise | Two forged commits to PHP 8.1-dev; caught before any release | BleepingComputer |
| 2021-04-01 (disclosed 04-15) | Codecov Bash Uploader | Distribution infrastructure compromise via leaked credential | 62-day window; CI environment variables exfiltrated (AWS keys, deploy keys); downstream impact at HashiCorp, Twilio | Codecov |
| 2021-10-22 | ua-parser-js 0.7.29, 0.8.0, 1.0.0 | Maintainer account compromise (password reuse) | ~8M weekly downloads; cryptominer + Windows credential stealer; ~4-hour active window | Rapid7 |
| 2021-11-04 | coa / rc (npm) | Credential stuffing | Combined ~23M weekly downloads; Qakbot (Windows) and Linux credential stealers | Rapid7 |
| 2022-03-08 | node-ipc 10.1.0–10.1.2 + peacenotwar | Maintainer-initiated "protestware" | Files overwritten on systems geolocated to Russia/Belarus; ~1M weekly downloads; removed by npm within ~24h | Snyk · CVE-2022-23812 |
| 2025-03-14 | tj-actions/changed-files (GitHub Action) | Retroactive tag manipulation to malicious commit | Used in 23,000+ repos; secrets printed to public workflow logs; ~1-hour active window | CISA alert (CVE-2025-30066) |
| 2025-09-15 | tinycolor, ngx-bootstrap, ng2-file-upload + ~170 more (npm) | First self-replicating worm in npm | Credential exfiltration + GitHub Actions persistence + automated republishing | Snyk (original Shai-Hulud) |
| 2025-11-24 | 600+ npm packages including Zapier/Posthog/Postman tools | Second-generation worm; turns infected machines into self-hosted runners | 25,000+ compromised GitHub repos; destructive variants delete home directories | Snyk (SHA1-Hulud) |
| 2026-02-20 | 19 typosquats targeting claude-code / hardhat / supports-color | Third-generation worm; first to inject malicious MCP servers into AI coding assistants | AI toolchain poisoning vector documented for the first time | Endor Labs (SANDWORM_MODE) |
| 2026-05-11 → 2026-05-19 | @tanstack, Nx Console, @antv (and more) | Fourth-generation worm; first to forge valid Sigstore provenance and SLSA L3 attestations | OpenAI code-signing certs stolen; ~3,800 GitHub repos exfiltrated; 1,055 malicious versions across 502 packages campaign-wide | Microsoft Security (Mini Shai-Hulud) |
Three patterns are visible from the timeline itself, without speculation:
Cadence has compressed. The gap between major incidents was measured in years between 2016 and 2021. It is now measured in weeks. The same group, TeamPCP, has executed at least five distinct campaigns (Trivy, Bitwarden CLI, TanStack, Nx, AntV) in the eight weeks preceding this article.
Target value has escalated. The 2018–2021 wave was dominated by cryptominers and wallet stealers — opportunistic, financially motivated, modest blast radius per victim. The 2025–2026 wave targets cloud credentials, CI/CD tokens, source-code repositories, and AI-assistant configurations — assets where one successful theft becomes the next attack's initial access.
The trust boundary has moved upstream. Early attacks compromised the registry (typosquats, malicious uploads). The middle wave compromised maintainer accounts (password reuse, no 2FA). The current wave compromises the CI runtime inside legitimate maintainer pipelines — and, as of May 2026, produces cryptographically valid provenance from that position. Each generation has moved the attack one step closer to the trust root, and most defenders' controls are still aimed at the previous generation.
For ten years, attackers have been getting better at hiding malicious software in the building blocks honest developers download. They used to be amateurs slipping bad packages into the marketplace. Now they have professional tooling, run new campaigns every few weeks, and steal the keys that unlock entire cloud accounts and corporate code repositories. The May 2026 wave is the first time their packages have come with a cryptographic certificate of authenticity that passes every automated check.
What actually happened, in order
The two waves had different blast radii but shared a single technique.
11 May 2026, 19:20–19:26 UTC — TanStack. A maintainer of the @tanstack scope had their GitHub Actions runner compromised. The attacker, tracked under the alias TeamPCP by StepSecurity and previously responsible for the March 2026 Aqua Trivy compromise and the April 2026 Bitwarden CLI compromise, pushed 84 poisoned versions across 42 @tanstack packages. Among the developers who installed those versions in the next 48 hours were two OpenAI employees. The payload exfiltrated credentials, including the certificates OpenAI uses to sign its desktop and mobile applications.
18 May 2026, 12:30–13:09 UTC — Nx Console. A side-effect of the TanStack compromise: a contributor's GitHub token, harvested in the first wave, was used to publish version 18.95.0 of the Nx Console VS Code extension (≈2.2M lifetime installs). The malicious version was live on the Visual Studio Marketplace for eleven minutes and on OpenVSX for thirty-six. According to Nx's own postmortem, internal telemetry showed roughly 6,000 activations during the window — almost entirely via auto-update. Official manual-download counts: 28. The payload specifically targeted Claude Code configuration files at ~/.claude/settings.json, alongside AWS keys, GitHub tokens, npm tokens with bypass_2fa scope, 1Password session data, and Kubernetes service-account tokens.
19 May 2026, 01:39–02:06 UTC — AntV. Two dormant npm packages — jest-canvas-mock and size-sensor, neither updated in over three years — published new versions containing an obfuscated ~498KB Bun script. Within 27 minutes the worm had propagated across the entire @antv visualisation ecosystem and dozens of unscoped packages, including echarts-for-react (~1.1M weekly downloads). Endor Labs, Snyk, and Microsoft's Security blog all published parallel analyses within 24 hours.
Across the full campaign — npm, PyPI, and Composer combined — Socket reports a total of 1,055 malicious versions across 502 packages, with a median detection time of 6.7 minutes from publication. That detection speed is genuinely impressive. It also wasn't fast enough — at 1.1M weekly downloads on echarts-for-react alone, six minutes is a lot of installs.
npm is the world's biggest catalogue of reusable JavaScript building blocks. Modern applications stitch together hundreds or thousands of them. An attacker who poisons one popular block reaches every application that uses it — and, in this case, every application that uses those applications. The reason "six minutes is a lot of installs" matters is that automatic update systems pull the poisoned version onto thousands of developer machines and build servers before any human notices.
Why "Mini" Shai-Hulud, and why it matters
The original Shai-Hulud worm appeared in September 2025, compromising tinycolor, ngx-bootstrap, and roughly 170 other npm packages via maintainer-account takeovers (Snyk's original write-up). That campaign was a worm: each compromised maintainer's tokens were used to publish poisoned versions of every other package they controlled.
"Mini" is the descriptor that has stuck since the April–May 2026 wave because individual blast radii are smaller — tens of packages per wave rather than hundreds — but the technique has evolved in one decisive way. The worm now mints its own valid Sigstore signing certificates at runtime, from inside the very CI/CD pipelines it has compromised, and submits them to the public transparency log. Every package it publishes carries a cryptographically valid attestation that says: this artifact was built in a legitimate GitHub Actions job under a legitimate identity.
That statement is true. It is also useless.
Until now, "supply-chain attack" mostly meant an attacker uploaded a fake package that looked like the real one. Defenders responded by building a system that cryptographically certifies which official build pipeline produced each package — a kind of digital factory seal. Mini Shai-Hulud is the first wave that, instead of forging the seal, breaks into the factory and uses the real seal-making machine. The certificates it produces are authentic. They just no longer mean "the code inside is safe."
How a worm forges valid provenance
Sigstore's trust model is straightforward. A build runs in a known CI environment (e.g., GitHub Actions). The runner requests an OIDC token from the CI provider using the ACTIONS_ID_TOKEN_REQUEST_TOKEN environment variable. It sends that token to Fulcio, Sigstore's certificate authority, which issues a short-lived X.509 certificate bound to the OIDC identity. The build signs the artifact with the cert's ephemeral private key. The signature, certificate, and metadata are logged to Rekor, the public transparency log. Anyone downstream can call cosign verify and confirm the chain.
The model verifies who built it and where it was built. It does not — cannot — verify whether the build did what it was supposed to do.
Mini Shai-Hulud sits inside the compromised CI runner. It has access to the same ACTIONS_ID_TOKEN_REQUEST_TOKEN. It makes the same legitimate calls to Fulcio and Rekor. The certificates it receives are bound to the real GitHub Actions job identity of the real maintainer's real pipeline. Every step is a legitimate API call to a legitimate service. As Vectra's analysis puts it, the runner has permission to make all of them.
What downstream consumers receive is therefore exactly what they would have received from an honest build: SLSA Build Level 3 provenance, a valid cosign signature, a Rekor entry. Every automated check passes. Chainguard's post-mortem is blunt: "Sigstore provenance tells you which pipeline produced an artifact, not whether that pipeline was behaving as intended."
This is not a bug in Sigstore. It is the operating envelope of Sigstore being publicly stress-tested for the first time.
Think of it like a courier service that verifies the sender's passport at pickup and stamps every parcel with the verified ID. The courier is doing its job perfectly. If a thief steals the sender's passport and walks into the courier's office with it, the parcel still gets stamped with a genuine verified-sender mark — because the courier has no way of knowing whose hand is holding the passport. The fix is not to redesign the courier's stamp. It is to keep the passport out of thieves' hands, and to stop treating the stamp alone as proof that the parcel is safe.
What this means for your trust model
When valid attestations can be produced from inside a compromised pipeline, Sigstore provenance becomes forensics, not a real-time gate. It tells you which pipeline built an artifact — evidence you use after an incident — not whether that pipeline was honest at build time. Any trust model that treats cosign verify as the final check before installation no longer holds in 2026.
Three claims are worth separating from the headline.
Provenance is forensics, not a control. When valid attestations can be produced by a compromised pipeline, provenance becomes evidence you use after an incident to trace what happened. It is not a real-time gate that blocks bad packages. If your security architecture has been treating Sigstore verification as a final trust check before installation, that assumption no longer holds in 2026. It probably never did; this is just the first time it has been demonstrated at scale.
The trust boundary moved upstream — and most defenders haven't moved with it. The compromise was not at the registry, not at the signing service, not at the verification step. It was inside the maintainer's CI environment. That means the controls that would have helped are the ones that protect the source repository and the build environment, not the ones that protect the artifact. Egress controls on CI runners, OIDC token isolation, runtime detection inside Actions runners, mandatory review of workflow file changes — these are the relevant controls now. Most organisations have not invested there because, until very recently, they didn't have to.
The certificate-theft angle has its own lessons. OpenAI lost code-signing certificates because the attacker, via a developer's machine, reached the keys. That is a separate, parallel control failure from the Sigstore story. Apple Developer ID certificates and Windows EV code-signing certificates are supposed to live in HSMs or hardware tokens. If they live on a developer laptop or in a CI server's filesystem, they are subject to exactly the same exfiltration as any other secret. OpenAI's June 12 deadline for macOS users to update to binaries signed with new certificates is, mechanically, what every vendor in this position has to do: revoke the old, issue the new from a more defensible store, force-update the client base before the old certs reach end-of-life.
What was actually taken, and where
The payload's targeting is precise and worth reading in full because it tells you what an attacker considers valuable in a 2026 developer environment.
According to StepSecurity, Microsoft, and Snyk's AntV write-up, the payload harvests:
- Cloud and platform credentials. AWS keys (including IMDSv2 metadata, Secrets Manager handles), HashiCorp Vault tokens, Kubernetes service-account material, Docker auth files.
- Source-control and registry tokens. GitHub tokens (with classic-PAT and fine-grained variants), GitLab tokens, npm publish tokens — including those with
bypass_2fascope. - CI/CD-platform identity. OIDC tokens scraped from GitHub Actions runner memory (
/proc/*/mem) to bypass GitHub's secret-masking, plus credentials for GitLab CI, Jenkins, Azure DevOps, CircleCI, Vercel, and Netlify. - Developer environment secrets. SSH keys,
.envfiles, database connection strings, 1Password session data (extracted from running agent processes), and — distinctively — Claude Code configuration files.
The data is gzip-compressed, AES-256-GCM encrypted, the symmetric key RSA-OAEP-wrapped, and transmitted over HTTPS to a hardcoded endpoint. A secondary channel uses the Session end-to-end-encrypted messenger network for exfiltration that is essentially indistinguishable from legitimate Session traffic at the network layer. A tertiary, opportunistic channel writes stolen data into newly-created repositories under the victim's own GitHub account, disguised as Dependabot-style branches — using the victim's own infrastructure as cold storage.
Network telemetry alone will not recover this. The point is worth making clearly: by the time outbound exfiltration is visible to a SOC, the attacker already has what they came for.
"Credentials" here means the keys, tokens, and passwords a developer's computer or build server uses to talk to cloud services, source-code platforms, and password managers. Stealing data is bad; stealing credentials is worse, because credentials let the attacker come back tomorrow and take whatever they want — directly, through the front door, looking exactly like the legitimate user. That is why this category of attack is so highly valued: it is initial access for the next attack.
The Claude Code configuration files: a small detail with a big implication
Worth pausing on. The Nx Console v18.95.0 payload specifically reads ~/.claude/settings.json. The 1Password vault contents and Claude Code configs are listed adjacent to AWS keys in the targeting. This is the first wave of malware we are aware of that treats an AI-coding-assistant configuration as a primary credential store on par with cloud keys.
It makes sense. A developer's Claude Code or Copilot config can contain MCP server credentials, API keys for connected services, project paths, and — increasingly — references to internal repositories the assistant has been authorised to read. An AI assistant that has been "set up well" is, by definition, a high-privilege identity in the developer's environment. Attackers have noticed. If your organisation has been thinking about AI assistant credentials as a productivity-tool concern rather than a privileged-identity concern, that gap has now closed.
A productive developer using an AI coding assistant typically connects it to their company's code repositories, cloud accounts, internal documentation, ticketing system, and password manager. The configuration file that stores those connections is a single document that grants access to a wide slice of the company. Most organisations have not yet started to treat that file the way they treat, say, an administrator's password. The attackers in May 2026 already did.
What this is, and is not, in regulatory terms
The EU compliance reading is straightforward.
NIS2 (Directive EU 2022/2555), Article 21(2)(d). Essential and important entities are required to implement supply-chain security measures including security in the relationship with direct suppliers. A compromised npm dependency that reaches production is, structurally, a supply-chain incident under this provision. Article 23's reporting obligations — 24-hour early warning, 72-hour detailed notification, one-month final report — apply if the incident causes "significant" operational disruption or material/non-material damage. For most organisations consuming the affected packages, the answer to "did this cause significant disruption?" will be no, and reporting is not triggered. For vendors distributing affected code to customers (the position OpenAI is in for its desktop apps, the position Nx is in), the answer is different.
DORA (Regulation EU 2022/2554), Articles 28 and 30. ICT third-party risk management is non-delegable. Whether an open-source npm dependency qualifies as an "ICT third-party service" supporting a critical or important function is genuinely contested — most legal readings treat unsupported OSS as outside DORA's scope but treat the use of OSS in a critical function as a risk the financial entity owns. In other words: DORA does not give you a way to point at npm and call it npm's problem.
Cyber Resilience Act (Regulation EU 2024/2847). Vulnerability and incident reporting becomes mandatory on 11 September 2026, with the full SBOM and conformity-assessment regime arriving 11 December 2027. CRA explicitly does not exempt open-source dependencies when they are integrated into a commercial product. Vendors are responsible for the full dependency tree. Six months from publication of this article, every vendor placing software on the EU market needs an answer to: "What is in your build, and how would you know if it changed?" Mini Shai-Hulud is the worked example of why that question matters.
European law now expects three things from organisations that build, sell, or operate software at any scale. NIS2: if you're a meaningfully sized business and a security incident disrupts your service or your customers, you have to tell regulators within 24 hours. DORA: if you're in financial services, you have to actively manage the risk that comes from every supplier — including the open-source code in your own product. CRA: by late 2026 and fully by late 2027, any software product placed on the EU market must come with a published list of its ingredients (an SBOM) and a process for handling vulnerabilities. Mini Shai-Hulud is not a hypothetical. It is the reason these rules exist.
What defenders should actually change
The honest version is: there is no single product that would have prevented every wave of this campaign. There are layered controls that materially reduce risk, and there is one control assumption that has to be retired. In rough order of leverage:
Treat Sigstore provenance as audit evidence, not as a real-time gate. When cosign verify passes, that tells you the artifact has a verifiable identity-chain. It does not tell you the code is clean. Build your trust model on multiple signals, including behavioural ones.
Add a cooldown between package release and consumption. Mini Shai-Hulud's two AntV waves were live for between 17 and 27 minutes before the worm exhausted its propagation. Tooling like StepSecurity's harden-runner and Socket's CI integrations can delay or quarantine new versions for a defined window. A 24-hour cooldown on production builds, with a separate exploratory channel for newer versions, would have caught most of the May 2026 waves before they reached production. The trade-off — slower access to bug fixes — is a real one. So is the alternative.
Run npm ci --ignore-scripts in CI. This is the simplest and most underused control on the list. It blocks the preinstall and postinstall hooks that Mini Shai-Hulud uses to gain its initial foothold. It breaks a non-trivial number of legitimate packages that do real work in postinstall, which is precisely why most of those packages should not be doing real work in postinstall. Adopting --ignore-scripts forces a conversation about which dependencies legitimately need build steps, and lets you allow-list those explicitly.
Enforce egress allow-listing on CI runners. GitHub Actions runners can reach the entire internet by default. They almost never need to. Outbound traffic from a build runner should be policy-controlled and logged — npm registry, container registries, the vendor's own infrastructure, and very little else. Behavioural detection of "this build job just made an outbound HTTPS connection to a domain it has never contacted before" is exactly the signal you want.
Get code-signing keys off developer machines. Hardware-backed signing — Apple Developer ID via Secure Enclave or external HSM, Windows EV certs in compliant tokens — does not prevent every attack. It does prevent the specific outcome where keys are exfiltrated alongside .env files. For software distributed to regulated EU entities (financial services, healthcare, critical infrastructure) this should be a hard requirement, not an aspiration.
Treat AI-assistant configurations as privileged credentials. ~/.claude/settings.json, Copilot tokens, Cursor configurations, and the MCP server credentials inside them now sit on the target list. The same controls that apply to AWS keys — short lifetimes, scoped privileges, rotation discipline, monitoring of which processes read them — should apply here.
Update TPRM questionnaires. "Do you require 2FA for npm publishers?" is necessary but not sufficient. "How do you protect signing keys?", "How do you isolate OIDC tokens in CI runners?", "What is your cooldown policy for new dependency versions in production builds?", "How are AI assistant credentials managed in your developer environment?" — these are the questions that map to the actual attack surface in 2026.
What this is not
This is not a vendor-specific CVE. There is no patch level that fixes the underlying class of attack. There is no Sigstore configuration change that makes the May 2026 mechanism stop working. Mini Shai-Hulud is a maturation of the supply-chain attack class — the proof of concept for an attacker who has read the SLSA specification carefully and decided to live inside its trust boundary rather than try to break it.
It is also not the end of the wave. The same attacker group, TeamPCP, has hit Aqua Trivy (March), Bitwarden CLI (April), TanStack (May 11), Nx (May 18), and AntV (May 19), with each campaign showing more sophistication than the last. The packages on this list are not exotic. They are the boring infrastructure that ships in everyone's dependency tree. The next campaign will look like this one but slightly different. The controls that helped or didn't help in May 2026 are the controls that will matter in the next wave.
The trust signal worked exactly as designed. The system is doing what we asked it to do. It just turns out we asked for the wrong thing.
Glossary
A non-developer reader-friendly definition of the technical terms used above.
npm. The largest catalogue of reusable JavaScript building blocks in the world (around 3 million packages). When a developer writes a modern web or mobile application, npm is where most of the ingredients come from. A single application typically depends on hundreds of npm packages, which in turn depend on hundreds more.
Package. A reusable piece of code published to a registry like npm. Each package has a name, a version number, and a list of other packages it depends on.
Transitive dependency. A package that your project does not directly install, but that one of your direct dependencies installs on your behalf. Most security incidents in this article happened through transitive dependencies — code that organisations did not knowingly choose to use.
CI/CD pipeline. The automated assembly line that turns source code into a deployable product. "CI" (continuous integration) compiles and tests; "CD" (continuous delivery or deployment) ships the result. Modern CI/CD runs unattended in cloud infrastructure (GitHub Actions, GitLab CI, Jenkins, CircleCI). Because it runs unattended, it holds the credentials needed to deploy software — making it a high-value target.
Postinstall hook (or postinstall script). A script that an npm package can ask to be run automatically on the user's machine immediately after the package is installed. Legitimate packages use this for setup steps. Malicious packages use it to run their payload the instant the package lands.
Worm. A type of malicious software that spreads from one system to another without human action. In the npm context: an attacker compromises one package, the package's payload steals credentials from each machine it lands on, and those stolen credentials are used to publish poisoned versions of other packages the same maintainers control, accelerating spread.
Exfiltration. The act of secretly sending stolen data from the victim's system to a system the attacker controls.
Code-signing certificate. A cryptographic credential that lets a software publisher prove that a specific binary (a macOS app, a Windows installer, an iOS or Android app) really came from them. Operating systems trust the signature when you install or update software. Stealing the certificate lets an attacker publish software the operating system will trust as if it came from the original vendor.
HSM (Hardware Security Module). A tamper-resistant physical device — sometimes a card, sometimes a server appliance — that stores cryptographic keys and performs signing operations inside the device, so the key itself never leaves. The standard defence against the "keys stolen from a developer laptop" failure mode.
Sigstore. An open-source service (run as a public-good utility by the Open Source Security Foundation) that lets software publishers cryptographically sign artefacts and record those signatures in a public, append-only log. It is designed to give downstream consumers a way to verify that a package really was built where it claims to have been built. The May 2026 worm proved that Sigstore verifies which build pipeline signed an artefact, but not whether that pipeline was honest at the time.
Provenance. In the supply-chain-security sense: a verifiable record of how a software artefact was produced — which source-code commit, which build pipeline, which environment, which timestamp. Sigstore is the most widely deployed mechanism for producing provenance.
SLSA (Supply-chain Levels for Software Artifacts). A specification, pronounced "salsa", that defines four progressive levels of supply-chain assurance for software builds. SLSA Level 3 is the level reached by a build pipeline that uses an isolated, well-audited build environment with cryptographically signed provenance. The May 2026 worm produced packages with valid SLSA Level 3 provenance.
OIDC token (OpenID Connect token). A short-lived digital identity badge that a system can present to prove "I am who I say I am" to another system. In CI/CD, OIDC tokens are how a build job proves to Sigstore that it really is running inside (for example) a particular GitHub Actions workflow. The Mini Shai-Hulud worm steals or re-uses these tokens to mint valid signing certificates from inside the compromised pipeline.
MCP server (Model Context Protocol server). A program that exposes data or capabilities — files, databases, APIs, internal tools — to an AI coding assistant in a structured way. A developer's AI assistant configured with MCP servers becomes a high-privilege identity, because the assistant (and anyone who steals its configuration) can reach everything the MCP servers expose.
Primary sources
- OpenAI, Our response to the TanStack npm supply-chain attack.
- Nx, Nx Console v18.95.0 postmortem.
- StepSecurity, Mini Shai-Hulud is back: a self-spreading supply-chain attack hits the npm ecosystem.
- Endor Labs, Mini Shai-Hulud returns: 42 malicious npm packages, fake Sigstore badges in @antv ecosystem attack.
- Microsoft Security, Mini Shai-Hulud: compromised @antv npm packages enable CI/CD credential theft.
- Snyk, Mini Shai-Hulud: AntV npm supply-chain attack.
- Socket, TanStack npm packages compromised in Mini Shai-Hulud supply-chain attack.
- Vectra, Shai-Hulud Part 2: When the worm forged its own security certificate.
- Chainguard, Mini Shai-Hulud npm attack: AntV ecosystem compromise.
- Tenable, Mini Shai-Hulud frequently asked questions.
- Snyk, Embedded malicious code in tinycolor and ngx-bootstrap releases on npm (original Shai-Hulud, September 2025).
Historical-timeline sources
- npm Blog, kik, left-pad, and npm (March 2016).
- npm Blog, Reported malicious module: getcookies (May 2018).
- ESLint, Postmortem for malicious packages published on July 12th, 2018.
- Snyk, A post-mortem of the malicious event-stream backdoor (November 2018).
- Sophos News, Bootstrap supply-chain attack is another attempt to poison the barrel (April 2019).
- CISA, Emergency Directive 21-01 — Mitigate SolarWinds Orion code compromise (December 2020).
- Alex Birsan, Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies (February 2021).
- BleepingComputer, PHP's Git server hacked to add backdoors to PHP source code (March 2021).
- Codecov, Security update (April 2021).
- Rapid7, NPM Library (ua-parser-js) hijacked: what you need to know (October 2021).
- Rapid7, New NPM library hijacks: coa and rc (November 2021).
- Snyk, Alert: peacenotwar module sabotages npm developers and CVE-2022-23812 (March 2022).
- CISA, Supply-chain compromise of third-party tj-actions/changed-files (CVE-2025-30066) (March 2025).
- Snyk, SHA1-Hulud: npm supply-chain incident (November 2025).
- Endor Labs, SANDWORM_MODE: dissecting a multi-stage npm supply-chain attack (February 2026).
EU regulatory references
- NIS2 Directive (Directive EU 2022/2555), Articles 21 and 23.
- Digital Operational Resilience Act (Regulation EU 2022/2554), Articles 28 and 30.
- Cyber Resilience Act (Regulation EU 2024/2847), Annex I and timeline.