A Malicious npm Package Hid Its Payload in a Function Call, Not an Install Script
Checkmarx found that indexed-btree, downloaded nearly 2 million times a week, moved its trigger into ordinary runtime code to sidestep the install-script restrictions npm shipped in July 2026.
On 17 September 2026, researchers at the software supply-chain security firm Checkmarx disclosed a malicious npm package, indexed-btree, that had been downloaded almost 2 million times a week while posing as an ordinary B-tree data-structure library. The package did not need a victim to run npm install and trigger a setup script, the route npm closed off in July 2026. Instead, its loader sat inside a function developers were expected to call in the normal course of using the library.
What changed
indexed-btree impersonated sorted-btree, a genuine and widely used indexing utility, and was first published to the npm registry on 18 June 2026 under the account "charlessadler25," according to reporting by The Hacker News. Rather than placing malicious code in a preinstall or postinstall hook, the loader for a second-stage payload, sharedLoad.min.js, was embedded inside BTree.prototype.set() — the method an application calls every time it inserts a value into the tree. Because the trigger fires during normal use rather than at install time, it never touches the controls npm added specifically to catch install-time malware.
Checkmarx researcher Bruno Dias put the finding directly: "npm v12 provided a big shift by blocking lifecycle scripts but this is not stopping attackers." Nine related packages built around the same theme — names such as btree-core, btree-range-store and neighbor-key-map — carried the same loader and were traced to the same campaign before being pulled from the registry.

How the malware worked
Once triggered, the code fingerprinted the host — operating system, architecture, hostname, CPU, memory and uptime — and exfiltrated the data through a hardcoded Slack bot token and a Telegram bot, according to Checkmarx's technical writeup. For command and control, it queried a smart contract deployed on the Ethereum Sepolia test network, generating a fresh X25519 keypair for each infection, exchanging it with the attacker's public key, and deriving an AES key to decrypt further payloads. This is a technique known as EtherHiding, which lets an attacker update or reroute a campaign without registering a domain that defenders can seize or block, as BleepingComputer's independent review of the campaign also noted. The malware included a self-cleanup routine capable of deleting its own files and stripping the trigger back out of the prototype method it had modified. Checkmarx traced roughly 109 ETH, worth about €230,933.57 at the time of reporting, moving through wallets tied to the operation.
Why the timing matters
The attack lands two months after npm's most significant defensive change in years. Version 12 of the npm CLI, released on 8 July 2026, switched allowScripts off by default, so preinstall, install and postinstall hooks no longer run automatically on npm install — developers now have to explicitly approve them with npm approve-scripts, as The Hacker News reported when the release shipped. Git and remote-tarball dependencies were restricted the same way. The change targeted the single most common delivery mechanism in registry malware: code that runs the moment a package is installed, before anyone has read a line of it.
indexed-btree shows what happens once that door closes: the payload moves downstream, into code paths a static install-time scanner has no particular reason to flag, because calling a library's own documented method is exactly what a legitimate integration looks like. The package sat live on the registry for roughly three months — from 18 June until Checkmarx's disclosure in September — accumulating downloads the entire time, which suggests the runtime placement delayed detection as much as it evaded any specific control.
What it means for dependency review
For teams that maintain software bills of materials or run automated dependency scanning, the case argues for treating a package's exported functions, not just its install hooks, as part of the attack surface. Static analysis that checks only lifecycle scripts, or reputation scoring based on download counts and repository activity, would not have caught this: the campaign maintained a convincing, actively updated GitHub repository to build the trust that let it accumulate downloads for months, according to Checkmarx. Runtime monitoring, outbound network allowlisting for build and application environments, and behavioral detection of unexpected blockchain RPC calls from what is supposed to be a data-structure library are the kinds of controls that would surface this pattern; none of them are yet standard practice in most JavaScript build pipelines.

Checkmarx has published indicators of compromise alongside its report, including the contract address, bot tokens and hardcoded RPC endpoints used by the campaign. Neither npm nor GitHub had issued a public statement specific to this campaign at the time of writing; the packages named in Checkmarx's disclosure are no longer available through the registry.
- Bruno Dias. npm 'btree' Malware Campaign Affects Millions of Downloads, No Need for Install Script. Checkmarx Zero, 2026. link
- Ravie Lakshmanan. Malicious npm Package indexed-btree Hid Its Loader in Runtime Code Before Removal. The Hacker News, 2026. link
- BleepingComputer. Malicious npm packages evade install-script defenses at runtime. BleepingComputer, 2026. link
- The Hacker News. npm 12 Disables Install Scripts by Default to Reduce Supply Chain Risk. The Hacker News, 2026. link