A malicious npm package hid malware in its own code
A JavaScript package with almost two million weekly downloads carried malware that fired only when developers used it, sidestepping npm's new defences against install scripts.

What Checkmarx found inside indexed-btree
A JavaScript package that hundreds of thousands of developers pull down every week was carrying malware that no install script would ever have shown them, according to research Checkmarx published on 20 September. The package is called indexed-btree and it mimics the API of a legitimate library called sorted-btree closely enough that its code looks ordinary in review.
The registry entry now tells its own story. npm replaced indexed-btree with a placeholder security release on 3 September 2026, after functional versions 2.1.1, 2.1.2 and 2.1.3 shipped between June and July. npm's own download counters recorded 1,792,676 downloads of the name in the week to 19 September, while the library it copied, sorted-btree, logged 795,994 in the same seven days. Checkmarx describes the total as close to two million a week.
Nothing about the package's public face is obviously wrong. It has a GitHub repository with a plausible commit history and an avatar, which Checkmarx notes was still online at the time of writing. The firm describes it as a deliberately built disguise rather than a rushed typosquat.
Why installing it did nothing
In June 2026 GitHub announced a set of npm protections built to blunt the supply-chain attacks that have repeatedly hit open-source ecosystems. The headline change was to block dependency lifecycle scripts such as preinstall, install and postinstall unless a developer explicitly approves them, which killed the standard trick of hiding a payload in the moment a package is installed.
indexed-btree does not use a lifecycle script at all. Checkmarx found the loader sitting inside BTree.prototype.set(), the method that every application importing the library calls constantly. When it is called with the key value 100, the method spawns a bundled, heavily obfuscated file, extended/sharedLoad.min.js, as a detached child process. Install the package and nothing happens; use it as intended and the malware starts.
"The malware loader hides inside the library's own BTree.prototype.set method, which is the main function that every user would call constantly," Checkmarx writes. "This is a well-built way to sneak past standard taint-analysis tools and most static scanners."
A smart contract for a command channel
Once running, the first stage collects the host's architecture, hostname, processor model, memory and uptime, and exfiltrates the bundle through hardcoded Slack and Telegram channels. Instead of a conventional command-and-control server it queries an Ethereum smart contract for instructions, reported by BleepingComputer as running on the Sepolia test network, and uses X25519 key exchange to derive an AES key that decrypts a second-stage payload stored in the contract.
That design makes the operation hard to shut down: there is no single server to seize, and Checkmarx says the malware can delete its own files and strip the trigger from the package code when the operators decide they are finished, wiping its traces behind them.
Checkmarx adds that the attackers' wallet holds 109 ETH, or roughly 230,934 euros, while cautioning that the report does not attribute those funds to stolen cryptocurrency. Nine further packages tied to the same operation have been removed from npm.
What to do about it, and what is still unknown
Checkmarx's advice is blunt: anyone who installed indexed-btree should treat their credentials as exposed, rotate secrets and rebuild the development environment from a clean backup. It also argues that install-time scanning is no longer a sufficient control, because the malicious behaviour now only appears while the code is running.
What the research does not say is how many organisations actually pulled the package in, which applications depended on it, or who is behind the campaign. The download count shows reach, not victims, and the disguise includes no obvious fingerprint pointing at a known group.
Our opinion
The interesting part of this campaign is not the smart contract or the 109 ETH. It is the timing. GitHub spent 2026 closing the front door on install scripts and, within months, attackers simply walked their payload through the living room instead, because the code a developer imports is the code that runs in production and always was. That is the uncomfortable lesson for anyone who treats a clean dependency install as evidence of a safe dependency: the approvals dialogue was never the security boundary. If there is a practical takeaway beyond rotating secrets, it is that the review effort belongs where the library actually executes, on the code paths a project calls on every request, which is precisely where nobody has time to look and precisely where this thing was waiting.