Join our Newsletter — 33% off our NHI Course
Home› Guides› Self Propagating Supply Chain Worms: How Registry Worms…
Guide Software & AI Supply Chain

Self Propagating Supply Chain Worms: How Registry Worms Spread and How to Break the Loop

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 8 November 2026 13 min read
On this page

A self-propagating supply chain worm turns each developer or CI credential it steals into the means of publishing its next infection, so one compromised maintainer can poison hundreds of packages in hours. Since Shai-Hulud hit npm in September 2025 the pattern has repeated across registries and tools: GlassWorm in VS Code extensions, CanisterSprawl and ChainDrop on npm, and Miasma and Hades across npm, PyPI and GitHub. This guide treats registry worms as a threat class rather than a single campaign. It explains the propagation loop they share, compares the known families, and sets out the controls that break each link: install-time execution, credential exposure, publishing rights and release workflows. It is for platform, AppSec, DevOps and identity teams who consume or publish open source packages. For the detail of one family see the Shai-Hulud npm Worm Guide, and for incident handling the Malicious Package Worm Response Playbook.

Key takeaways

  • Worms spread on identities, not exploits. Every family so far propagates by authenticating to a registry as the victim with a stolen publishing token or a hijacked CI identity, then republishing the victim's other packages.
  • Install time and open time are execution time. Lifecycle scripts, native build files, Python .pth files and AI coding tool trigger files all run code before anyone has used the package.
  • Trusted publishing narrows the loop but does not close it. ChainDrop and Miasma published through OIDC trusted publishing after taking over maintainer GitHub accounts: provenance proved the build path, not the honesty of the identity behind it.
  • Containment is a credential problem. CISA's first advice for Shai-Hulud was to rotate all developer credentials and require phishing-resistant MFA, not just to remove a package version.
  • Delay and isolate. A cooldown before adopting new versions, install scripts disabled in CI and release jobs separated from jobs that install third-party code defeat most waves seen to date.

What makes a supply chain worm different

A conventional malicious package waits to be installed. A worm adds a propagation step: once it runs on a maintainer's laptop or a CI runner, it looks for credentials that can publish, uses them to inject itself into every package those credentials can write to, and publishes new versions. Each new version infects more installers, some of whom are maintainers too. The Computer Worms Guide covers network worms; registry worms differ because their "network" is the dependency graph and their "exploit" is a valid credential.

The loop has five links, and every control in this guide breaks one of them:

  1. Entry: a maintainer account, token or CI workflow is compromised (phishing, a leaked token, an earlier infection).
  2. Execution: the trojanised version runs code automatically at install, build or repository open.
  3. Harvest: the payload collects publishing tokens, Git hosting tokens, cloud keys and CI secrets from files, environment variables, metadata endpoints and runner memory.
  4. Propagation: stolen publishing rights are used to enumerate and republish the victim's packages.
  5. Exfiltration and persistence: secrets leave through public repositories, webhooks or takedown-resistant channels, and backdoor workflows or runners keep access.

Known families compared

The table summarises the campaigns NHI Mgmt Group has analysed. Families are listed by first appearance.

FamilyWhenEcosystemsExecution triggerPropagation credentialDistinctive trait
Shai-Hulud (ATT&CK S9008)From September 2025; second wave November 2025npm, GitHubpostinstall, then preinstallnpm tokens; GitHub PATs for exfiltrationCISA reported more than 500 packages compromised in the first wave; secrets dumped to public repositories named Shai-Hulud
GlassWormFrom October 2025, waves to April 2026Open VSX, VS Code Marketplace, npmExtension activationLeaked extension publishing tokens, then harvested npm, GitHub and Open VSX credentialsInvisible Unicode code; command addresses read from Solana transactions
Mini Shai-Hulud (S9043)2026npm, GitHub ActionsInstall hooks, AI agent configuration hooksShort-lived CI identity tokens scraped from runner memoryATT&CK attributes it to TeamPCP (G1056)
CanisterSprawlApril 2026npm, PyPIpostinstall ending in || true; Python .pthAny npm publish token found; PyPI credentialsVersions published without matching git tags; exfiltration to an Internet Computer canister
Miasma and Hades1 to 7 June 2026npm, PyPI, GitHubpreinstall, binding.gyp, .pth, AI tool trigger filesHijacked GitHub account pushing to repos whose CI used trusted publishingReached Microsoft and Red Hat repositories; GitHub disabled 73 repositories
ChainDrop4 August 2026npmInstall-time payloadMaintainer GitHub takeover, project release workflow via trusted publishing, then stolen npm tokens444 packages and 2,212 malicious versions in about four hours; Ethereum contract for command addresses

Read the incident analyses: Shai-Hulud npm Worm 2025, GlassWorm Campaign 2025, CanisterSprawl npm Worm 2026, Miasma and Hades Worms 2026 and ChainDrop npm Worm 2026. The Top 10 Supply Chain Attacks page puts worms alongside the other supply chain attack types.

How worms map to ATT&CK

The techniques below are recorded in ATT&CK v20 against Shai-Hulud and Mini Shai-Hulud and recur across the other families.

Loop linkTechniqueControl that breaks it
EntryT1195.001 Compromise Software Dependencies and Development ToolsRelease cooldown, lockfiles, phishing-resistant MFA for maintainers
ExecutionT1546.016 Installer Packages; T1059.007 JavaScriptInstall scripts disabled in CI, allow-list for the few packages that need build steps
HarvestT1552.001 Credentials In Files; T1528 Steal Application Access TokenNo long-lived tokens on disk or in environment variables; short-lived, workload-bound credentials
PropagationT1550.001 Application Access TokenTrusted publishing, tokens disallowed for publishing, single-package scoping, release approval
Persistence in pipelinesT1677 Poisoned Pipeline ExecutionBranch protection, code owner review of workflow files, alerts on new self-hosted runners
ExfiltrationT1567.001 Exfiltration to Code RepositoryOrg policy blocking public repository creation and visibility changes; egress allow-lists on runners
ImpactT1098 Account Manipulation; T1485 Data DestructionAudit log alerts on visibility flips; workstation backups
  • Disable lifecycle scripts in CI: Set npm's ignore-scripts for dependency installs in CI and maintain an explicit allow-list of packages that genuinely need a build step. Recent package managers increasingly block dependency build scripts by default; check yours. See the npm Install-Time Security Guide.
  • Remember the other triggers: Miasma used binding.gyp to run during native builds, CanisterSprawl and Hades dropped Python .pth files that execute at interpreter start-up, and several families planted AI coding tool configuration that runs when a repository is opened. Scanning only package.json scripts misses these.
  • Install in a throwaway environment: Run dependency resolution and builds in ephemeral containers with no credentials mounted, then pass only the built artefact to later stages.
  • Control editor extensions: Use an allow-list and pinned versions for IDE extensions, as GlassWorm showed that extension marketplaces carry the same risk as package registries. See the GlassWorm VS Code Extension Worm Guide.

A publishing credential is both the worm's loot and its engine, so the strongest single control is making publishing rights unreachable from any environment that runs third-party code.

Publishing approachWhat a worm can do with itResidual risk
Long-lived token on a laptop (.npmrc, .pypirc)Read it and republish every package it coversHighest: the first-wave Shai-Hulud and CanisterSprawl path
Granular token, single package, short expiryRepublish one package until expiryLimits blast radius; still stealable
Local publish with 2FA required, tokens disallowedCannot publish without the second factorPhishing of TOTP codes; prefer FIDO-based 2FA
Trusted publishing (OIDC from CI)Only by running inside the authorised workflow, or by taking over the account that can change itAccount takeover and poisoned commits (ChainDrop, Miasma); runner memory scraping (Mini Shai-Hulud)
Trusted publishing with protected environment and human approvalMust also get a reviewer to approve the releaseLowest; costs release speed

npm's trusted publishing uses OIDC from GitHub Actions, GitLab CI/CD and CircleCI cloud runners (self-hosted runners are not supported at the time of writing) and needs npm CLI 11.5.1 or later. After it works, npm recommends selecting "Require two-factor authentication and disallow tokens" under the package's publishing access settings. GitHub's September 2025 plan for npm set out local publishing with required 2FA, granular tokens limited to seven days, trusted publishing, deprecation of classic tokens and a move from TOTP to FIDO-based 2FA. PyPI offers an equivalent trusted publisher model. See the npm Trusted Publishing and Provenance Guide, the PyPI API Tokens and Trusted Publishing Security Guide and the Package Registry Security Comparison Guide.

  • Bind OIDC trust narrowly: Trust one repository, one workflow file and one protected environment with required reviewers, not "any workflow in the organisation".
  • Separate release from build: The job that holds publishing identity should not run npm install on untrusted dependencies; build in one job, publish the artefact from another.
  • Protect the human account: Phishing-resistant MFA, session revocation after any suspected compromise, and code owner review on release workflow files. Provenance confirms where a package was built, not whether the person who triggered the build was legitimate.
  • Minimise runner secrets: Inject only the secrets a job needs, prefer cloud OIDC federation to stored keys, and require IMDSv2 on cloud runners.

Breaking the entry link for consumers

  • Cooldown before adoption: Do not resolve versions younger than a set age (for example 3 to 7 days) in builds. Most worm versions were detected and removed within hours or days. Several package managers and dependency bots now offer a minimum release age setting.
  • Lockfiles and pinning: Commit lockfiles, use npm ci rather than npm install in CI, and pin to known-good versions during an active campaign, as CISA advised.
  • Proxy through a curated repository: An internal artefact repository lets you block a version once for the whole organisation and search cached copies, another CISA action.
  • Watch for anomalies in what you consume: New versions without a matching git tag (the CanisterSprawl tell), sudden maintainer changes, new install scripts and unexpected native build files.

Implementation: a phased programme

  1. Inventory (week 1 to 2): List every package your organisation publishes, every token that can publish them, every IDE extension in use, and every CI workflow with publishing or cloud rights. See the npm Tokens Security Guide.
  2. Remove stored publishing tokens (week 2 to 6): Move releases to trusted publishing, then disallow tokens. Pilot on low-download packages first; roll back by re-enabling a short-lived granular token if a release is blocked.
  3. Disable install scripts in CI (week 3 to 8): Start in report mode by logging which packages run scripts, build the allow-list, then enforce. Keep the previous runner image available to revert.
  4. Introduce a cooldown (week 4 to 8): Apply the minimum release age to automated dependency updates first, then to all resolution, with a documented override for urgent security fixes.
  5. Harden release workflows (week 6 to 10): Protected environments, required reviewers, code owners on .github/workflows, and organisation policy blocking public repository creation by members.
  6. Exercise (quarterly): Run a tabletop on a worm hitting one of your maintainers, timing how long it takes to revoke every token they hold.

Small versus large organisations: A small team that only consumes packages gets most protection from lockfiles, a cooldown and scripts off in CI. Organisations that publish widely used packages need the full publishing controls, because they are the propagation path for everyone downstream.

Detection and measurement

  • Monitor: registry publish events for your packages without a matching tag or workflow run; new public repositories or visibility changes in your Git organisation; new self-hosted runners; new or changed workflow files; outbound connections from runners to webhook services (CISA advised blocking webhook.site), blockchain RPC endpoints or unknown domains; secret scanning alerts on your organisation.
  • KPI: publishing tokens outstanding. Count of long-lived tokens that can publish your packages; target zero.
  • KPI: trusted publishing coverage. Share of published packages released only through OIDC with tokens disallowed.
  • KPI: CI installs with scripts enabled. Share of pipeline dependency installs that still run lifecycle scripts.
  • KPI: cooldown coverage. Share of builds that enforce a minimum release age.
  • KPI: time to revoke. Minutes from a maintainer compromise alert to revocation of every token and session they hold.

Framework mapping

FrameworkReferenceRelevance
NIST SP 800-53 Rev. 5SR-3 Supply Chain Controls and Processes; SR-4 Provenance; SR-11 Component AuthenticityControlling and verifying what enters the build
NIST SP 800-53 Rev. 5IA-5 Authenticator Management; SA-10 Developer Configuration Management; CM-7 Least Functionality; SI-7 Software, Firmware, and Information IntegrityPublishing credentials, release workflow control, scripts off, integrity checks
NIST CSF 2.0GV.SC-07; PR.AA-01; PR.PS-02; DE.CM-09Supplier risk, credential management, software maintenance, monitoring of runtime environments
MITRE ATT&CK v20T1195.001, T1546.016, T1552.001, T1528, T1550.001, T1677, T1567.001Worm behaviour, see the table above

Common failure patterns

  • Removing the bad version and stopping: The tokens the worm stole remain valid, so the next wave publishes again. Rotate every credential reachable from the infected host, and clean the host before rotating so new secrets are not stolen too.
  • Treating provenance as proof of safety: ChainDrop's malicious keyv release came from the project's own release workflow through trusted publishing after a maintainer GitHub account takeover.
  • Publishing from the same job that installs dependencies: Any install-time payload in that job can reach the publishing identity, the path Mini Shai-Hulud used by scraping runner memory.
  • Leaked tokens in public code: GlassWorm began with extension publishing tokens developers had committed to public repositories. Run secret scanning on every repository and treat a leaked publishing token as a compromise.
  • Watching only npm scripts: .pth files, native build files and AI tool configuration triggered execution in later waves.
  • Organisation-wide OIDC trust: A trusted publisher bound to any workflow or branch lets one compromised contributor publish.

Practitioner checklist

  • Inventory every package you publish and every credential that can publish it, and remove long-lived publishing tokens.
  • Move releases to trusted publishing bound to one workflow and a protected environment with reviewers, then disallow tokens.
  • Require phishing-resistant MFA on registry and Git hosting accounts for all maintainers.
  • Disable dependency lifecycle scripts in CI with an explicit allow-list, and check for .pth, native build and AI tool trigger files.
  • Enforce a minimum release age on dependency resolution and automated update bots.
  • Separate build jobs that install third-party code from release jobs that hold publishing identity.
  • Block runner egress except to required registries, and alert on webhook services and new public repositories.
  • Allow-list and pin IDE extensions.
  • Rehearse revoking every token and session for one maintainer and measure the time it takes.

Standards and references

Related NHI Mgmt Group resources: Shai-Hulud npm Worm Guide · Malicious Package Worm Response Playbook · npm Trusted Publishing and Provenance Guide · Top 10 Supply Chain Attacks

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 8 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org