ProBackend
supply chain attacks
4 hours ago4 min read

Don't Trust the Install Step: indexed-btree and the New Era of Runtime npm Malware

The indexed-btree campaign hides its payload in a B-tree method that runs at runtime, sidestepping the lifecycle-script blocks GitHub shipped in 2026. Here's how the trick works, why LofyGang and Shai-Hulud saw it coming, and what actually defends against malware that waits.

When the Install Step Goes Quiet

The install script was always the tell. For a decade, the moment a malicious npm package had to do anything bad, it had to reach for a preinstall, install, or postinstall hook — and those hooks were the first thing every scanner learned to watch. So when the maintainers of npm's front door finally started blocking lifecycle scripts by default, it should have closed the door. Instead it just moved the attack.

That's the real lesson of the ongoing indexed-btree campaign, spotted by Checkmarx researchers. There is no install script to inspect, no obvious payload to flag, and nothing that trips an approval prompt during setup. The malicious code hides inside a function the legitimate library is supposed to run — a B-tree operation that developers might call days or weeks after installation.

The package name matters because it looks ordinary. indexed-btree is a data-structure library, not a tool that should need network access or shell execution. Yet the compromised version uses a normal-looking method call as the trigger for behavior that has nothing to do with maintaining an index. That is the bypass: don't execute when the package is installed; execute when the application uses it.

What the Researchers Found

Checkmarx described a malicious npm package that keeps its harmful logic dormant until runtime. The payload is not launched through npm's lifecycle hooks, so protections that simply suppress install scripts do not catch it. The code is embedded in the package's normal execution path and can look like ordinary library behavior during a quick review.

This changes the defender's timing problem. An install-time scanner may examine package metadata and lifecycle scripts and see nothing suspicious. A developer can install the dependency, pass the build, and ship an application that only triggers the hidden behavior under a later code path. The package remains dangerous even when npm install appears routine.

The reported campaign emphasizes why package review must include the code that executes when library APIs are called, not only scripts that run during installation. A malicious dependency can abuse expected application activity as its launch point, making runtime monitoring and careful dependency provenance important parts of defense.

Why Lifecycle-Script Blocks Are Not Enough

Blocking install scripts is a useful reduction in exposure. It prevents a common route for immediate execution and can stop packages that rely on postinstall to fetch or launch a payload. But it cannot establish that every package is safe: JavaScript modules can execute code when imported or when exported functions are called.

The shift to runtime triggers makes several familiar controls less complete:

  • Install-time review sees only part of the story. Metadata and lifecycle hooks are not substitutes for inspecting package source and update history.
  • Behavior can be delayed. A dormant function may not run in test or build environments, then activate along a production path.
  • Legitimate APIs provide cover. A library's normal function gives malicious behavior a plausible reason to execute.
  • Later detection takes more evidence. Investigators may need runtime telemetry and dependency mapping to tie suspicious behavior back to a package.

Teams should keep lifecycle scripts disabled when practical, but pair that control with lockfile review, package provenance checks, dependency allowlists for sensitive systems, and monitoring for unexpected child processes or network connections from application workloads. Testing should exercise dependency code paths rather than merely confirming that packages install cleanly.

A Broader Pattern in npm Attacks

Runtime activation is part of a wider shift in software supply-chain attacks: attackers look for the gap between what a control checks and what a package can do after it is admitted. A package does not need an install hook if its exported code can wait for a legitimate call. Likewise, a popular package name or a clean installation does not prove that a particular version is trustworthy.

The important distinction is between reducing one execution surface and establishing trust. Lifecycle-script restrictions narrow the first; provenance, review, and runtime visibility help with the second. No single control is a complete answer, especially when dependencies run with the privileges of the application that imports them.

For teams responding to a suspected malicious dependency, identify affected versions from the incident advisory, compare lockfiles and deployment manifests, remove or replace the package, and investigate runtime activity from systems that imported it. Rotate exposed credentials if there is evidence they may have been accessed. Preserve package artifacts and logs for analysis rather than relying on a clean reinstall as proof that no compromise occurred.

Related coverage: Red Hat npm Packages Compromised in Supply-Chain Attack Distributing Miasma Malware and 187 npm Packages Compromised in Self-Propagating Shai-Hulud Attack.

The Bottom Line

The indexed-btree campaign is a reminder that malware does not have to announce itself during installation. It can wait for a normal API call, blend into expected execution, and turn a routine dependency into a runtime risk. Blocking lifecycle scripts remains worthwhile, but defenses need to follow packages beyond installation and into the behavior they introduce in production.

the install step goes quiet

More blogs