Skip to main content
  1. Tech Blog: AI, Security, Infrastructure & Open Source/

ChainDrop npm Worm — When Provenance Signs Malware

Osmond van Hemert
Author
Osmond van Hemert
Supply Chain Security - This article is part of a series.
Part : This Article

ChainDrop did not sneak malware past the software supply chain. It used the supply chain exactly as designed.

On August 4, 2026, attackers compromised the GitHub account of a maintainer behind keyv, a caching library embedded across the JavaScript ecosystem. They added malicious files and a preinstall hook to legitimate repositories. The projects’ own GitHub Actions workflows then built and published poisoned packages to npm—with valid OpenID Connect trusted-publisher provenance and valid SLSA Build Level 3 attestations.

That detail makes ChainDrop more than another malicious-package story. The signatures were real. The official pipeline produced the artifacts. The source entering that trusted pipeline was already compromised.

For teams investing in SLSA attestations and SBOM adoption, ChainDrop exposes a boundary that is easy to miss: provenance can prove where software came from without proving that the software is safe.

What Happened
#

The confirmed starting point was [email protected], published on August 4. Related packages in the maintainer’s ecosystem—including cacheable, flat-cache, file-entry-cache, and cache-manager—were also affected before the worm spread into packages controlled by unrelated organizations.

The incident’s reported scale changed rapidly as researchers found more poisoned releases. Early analysis counted 444 package names and 2,234 malicious versions; later estimates exceeded 1,300 packages. The foundational affected packages collectively receive enormous download volume, but raw download numbers are not the most important metric. The real blast radius comes from where these packages execute: developer workstations, CI runners, release systems, and cloud-connected build environments.

ChainDrop belongs to the Shai-Hulud malware family, which has evolved through several npm campaigns since 2025. It follows the automated credential-theft pattern seen in the TanStack npm compromise, but adds stronger propagation, alternative execution paths, and persistence aimed directly at modern developer tools.

How the Worm Executes
#

The initial repository modifications were small enough to blend into a normal release:

  • package.json gained a preinstall hook.
  • setup.mjs became the first-stage dropper.
  • Math_Symbol.js carried the heavily obfuscated second-stage payload.

When a developer or CI system ran npm install, setup.mjs detected the operating system and checked the machine’s locale. Russian-language systems were excluded, a common tactic used by malware operators to avoid targeting particular regions.

The dropper then downloaded Bun 1.3.13 from its official GitHub release and used it to launch the payload. That choice was deliberate: security products often tune detections around Node.js process behavior. Running the second stage through Bun gave the malware a less-monitored execution path while still using a legitimate JavaScript runtime.

Once active, ChainDrop searched broadly for credentials, including:

  • npm publishing tokens and GitHub personal access tokens;
  • GitHub Actions and OIDC tokens available to CI runners;
  • AWS, Azure, and Google Cloud credentials;
  • Kubernetes configurations and service-account tokens;
  • HashiCorp Vault tokens and SSH keys;
  • Slack, Stripe, database, and other API secrets;
  • credentials and configuration used by Claude Code and GitHub Copilot.

A compromised dependency could therefore become an identity breach spanning source control, package registries, cloud infrastructure, and production clusters.

From Credential Theft to Automated Propagation
#

ChainDrop did not stop after collecting secrets. When it found an npm token with publishing rights, it queried the registry for every package writable by that identity. It downloaded each current package, injected its two payload files, added the preinstall hook, incremented the patch version, and published the poisoned release.

That automation explains how one compromised maintainer could lead to infections across unrelated organizations. A poisoned dependency ran in another project’s CI environment, stole a publishing token, and used that token to compromise the next group of packages. The package registry became both delivery mechanism and replication network.

Stolen data was compressed and encrypted with AES-256-GCM. The encryption key was then wrapped with an embedded RSA-4096 public key. For exfiltration, the worm could use a victim’s GitHub token to create a public dead-drop repository. If that route failed, it used an Ethereum smart contract to retrieve active command-and-control domains—a technique often called EtherHiding.

This is the key progression from the earlier multi-wave npm worms: the attack chain no longer depends on one stable server, one runtime, or one compromised publisher. Every stolen identity creates another path forward.

Valid Provenance, Malicious Source
#

Some poisoned packages carried valid npm provenance because GitHub Actions really did build and publish them through the authorized workflow. SLSA did not malfunction. The attestation accurately answered its question: which workflow produced this artifact?

It could not answer the questions that failed earlier in the chain:

  • Was the source change independently reviewed?
  • Was the preinstall hook expected?
  • Did the release map to an approved pull request and tag?
  • Had an editor task or agent configuration appeared unexpectedly?
  • Should the build runner have held publishing and cloud credentials?

A cryptographically verifiable pipeline can faithfully build malware when malicious source enters before the build begins. Provenance remains valuable, but treating it as a binary “safe” label collapses source integrity, build integrity, and runtime behavior into one signal.

The practical lesson is not to abandon SLSA. It is to connect provenance to branch protection, reviewed source changes, release-event correlation, dependency scanning, and behavioral policy. Signed and safe are related goals, not synonyms.

IDE and AI-Agent Hooks Change the Response
#

ChainDrop also planted persistence outside node_modules:

  • .vscode/tasks.json could execute the payload when a developer opened the project in VS Code.
  • .claude/settings.json could trigger it when a Claude Code session started.
  • .github/copilot-instructions.md appeared in some variants as another way to influence the development environment.

That means deleting node_modules and reinstalling clean dependencies may not remove the compromise. Simply opening the repository after cleanup could execute the payload again.

Researchers also found a token-monitoring process that polled GitHub every 60 seconds. In some variants, revoking the stolen token could trigger a destructive secondary action. This makes remediation order unusually important: isolate and investigate the system before blindly rotating credentials from the infected machine.

What Teams Should Do Now
#

If a project installed affected versions on or after August 4, treat the workstation or CI runner as compromised—not merely the dependency tree.

  1. Isolate suspected systems. Remove network access where practical and preserve evidence before cleanup.
  2. Check exact resolved versions. Registry tags changed during the incident, so search lockfiles and SBOMs by package and version rather than package name alone.
  3. Hunt beyond node_modules. Inspect .claude/settings.json, .vscode/tasks.json, .github/copilot-instructions.md, unexpected GitHub Actions changes, and processes such as gh-token-monitor.
  4. Remove persistence before revocation. Follow current incident-response guidance and avoid rotating tokens from the suspected host.
  5. Rotate every reachable secret from a known-clean environment. Include npm, GitHub, cloud, Kubernetes, Vault, SSH, and third-party API credentials.
  6. Review registry and repository activity. Look for unexpected patch releases, public repositories, commits, workflow changes, and package publications.
  7. Rebuild runners and artifacts. Do not assume deleting one package restores trust to a long-lived build environment.

The affected-package count and indicators continued to evolve after disclosure. Use current advisories from npm and security researchers rather than relying on a static list copied into a ticket.

What Has to Change
#

ChainDrop reinforces the broader lessons from repeated npm supply chain attacks, but it also points to more specific engineering controls.

Protect release inputs. Require review for changes to manifests, lifecycle scripts, workflows, editor tasks, and AI-agent configuration. These files are executable security boundaries now.

Separate identities. A CI job that installs dependencies should not automatically receive credentials capable of publishing packages, modifying repositories, or reaching production infrastructure.

Use disposable runners. Ephemeral environments reduce persistence and make a full rebuild cheaper than attempting to establish that a long-lived runner is clean.

Restrict install-time behavior. Disable lifecycle scripts where possible. Where they are required, isolate them and monitor process creation, filesystem changes, and outbound network connections across Node.js, Bun, and other runtimes.

Correlate releases with intent. A valid attestation should be checked against an approved commit, pull request, tag, workflow version, and expected release event. An unexplained patch release deserves investigation even when its signature verifies.

Evaluate package behavior. Provenance tells you who built an artifact. Malware scanning, policy checks, and sandboxed execution help tell you what it does.

My Take
#

ChainDrop is the incident that should end the habit of presenting provenance as a green checkmark for safety.

SLSA and trusted publishing still matter. They raise the cost of forging a release and provide evidence that incident responders desperately need. But ChainDrop shows the danger of trusting any single control too much: once an attacker controls the maintainer identity or source entering the pipeline, automation turns that trust into leverage.

The most important change is architectural, not another scanner. Build systems should carry fewer secrets, release identities should be short-lived and narrowly scoped, and developer-tool configuration should receive the same scrutiny as executable source. AI coding agents and IDEs have expanded the set of files that can run code; security reviews need to expand with them.

ChainDrop did not defeat a trusted pipeline. It inherited one. The next generation of supply chain defense must verify not only who produced an artifact, but whether the source change was expected, reviewed, constrained, and consistent with what the package is supposed to do.

Sources: Zscaler ThreatLabz technical analysis, OPSWAT incident overview, and Harness analysis of SLSA provenance.

Supply Chain Security - This article is part of a series.
Part : This Article

Related