The Malware Moved Downstream: indexed-btree and the npm Install-Script Ban Bypass
In July, npm shipped one of the most consequential supply-chain defenses in years: version 12 stopped running dependency install scripts by default, cutting off the preinstall/postinstall hook that most npm malware relied on. On 6 October 2026, ReversingLabs documented the answer. Attackers have routed around the ban with a malicious package called indexed-btree — a mimic of the legitimate sorted-btree library — whose trigger is buried in the package’s own prototype method and fires the moment the application uses the library, not when it is installed. Barely two months after adoption, the measure is negated.
The detection comes from Checkmarx, explained by researcher Bruno Dias on the company’s application security testing blog and reported by ReversingLabs’ John P. Mello Jr. The mechanism is disarmingly simple. There is no install hook at all — the package.json is completely clean — so every install-time check passes and every reviewer glancing at the manifest relaxes. The loader sits inside btree.prototype.set, which means it executes in the application’s normal runtime context, with the application’s permissions and network access. Once running, the malware fingerprints the host, exfiltrates data over Slack and Telegram, and uses an Ethereum smart contract as a resilient command-and-control channel. “Attackers just moved to a new vector,” said Checkmarx research advocate Darren Meyer.
A clean package.json is no longer a trust signal
The most quotable warning in the ReversingLabs piece belongs to Waseem Ahmed, head of engineering at Secure.com: some researchers had cautioned when npm shipped the lifecycle change that the code still has to run at some point. “If you close the door at install time, a patient attacker moves one step downstream and runs it at import time instead.” Worse, the absence of an install script had quietly become a trust signal — reviewers would see no hooks and relax — and “the single heuristic that npm’s change encouraged people to rely on is exactly the heuristic this defeats.”
That last point deserves emphasis, because it generalises. Sonu Kapoor, a senior Angular consultant, noted the July measure may have signaled to security teams that install time is the moment a package becomes dangerous — but a dependency can wait until it runs in a production service, holding credentials, internal systems, and customer data. “That delay matters because the malicious activity can blend into normal application execution.” Jacob Krell of Suzu Labs put it structurally: a clean install tells you only that the package manager saw nothing suspicious; it says little about what happens when the application uses the package. Jason Soroko of Sectigo summarised the shift in one line: the attacker has moved from package installation to package use, which “makes relying solely on installation-time security checks insufficient.”
A sleeper cell with a fake identity
Two details elevate this above an ordinary typosquat. First, the activation model: KhaiCode CEO Aviram Jenik called it a “sleeper cell” — malware that waits for its normal API to be called, which he argued makes it “borderline impossible to detect” with static analysis that never exercises the path, leaving dynamic analysis of the running application as the only reliable detector. Second, the cover story: the operators built a fake but plausible GitHub repository with commit history and a developer profile complete with photo — and the public repository contains none of the malicious code, so scanning it turns up nothing. The registry artifact and the advertised source diverge, which is the same repository-vs-runtime gap OX Security just measured across 15,465 MCP servers: review the listing all you like; it is not what runs.
Contrast this with the campaign we covered this week: MALFEX’s fourteen-month postinstall operation, which exploited the old world of install hooks across eight packages and 40,000 downloads. indexed-btree is the new world’s proof of concept — no hooks, no manifest signal, patience instead of persistence. And as Black Duck’s Boris Cipot warned, removing the package does not fix things: affected teams must determine where it was present and whether it executed, hunt for exposed credentials, and rebuild from trusted sources. The operators’ command-and-control infrastructure, ReversingLabs notes, is still running. This is also the same build-vs-run substitution class as the SubQL artifact substitution — what you audit is not what executes.
What to do
- Stop treating “no install scripts” as a verdict. It is one negative signal about one phase. Gate decisions on runtime behavior analysis, not manifest inspection.
- Hunt for indexed-btree and its lookalikes, then assume execution. Check lockfiles for typosquats of utility libraries you actually call. If it was present where the code path ran, investigate as a compromise: host fingerprinting plus Slack/Telegram exfiltration plus smart-contract C2, with credential exposure in scope.
- Verify the artifact, not the repository. A plausible GitHub repo with a clean tree proves nothing about the published tarball. Compare registry contents against source, pin hashes, and distrust developer profiles you have not validated through another channel.
- Add runtime and binary analysis to the pipeline. Static scans and software composition analysis remain one layer — Cipot’s framing — but a loader inside
prototype.setonly reveals itself when the API is exercised. Exercise it in a sandbox before production does. - Rebuild, don’t just remove. Uninstalling the dependency leaves behind whatever the loader already did. Scope the blast radius first, rotate exposed secrets, and rebuild affected environments from trusted sources.
Verification note: the npm version-12 lifecycle change (July), the indexed-btree / sorted-btree mimicry, the prototype-method trigger, the btree.prototype.set loader location, Slack/Telegram exfiltration, Ethereum smart-contract C2, the clean package.json, the fake repository and developer profile, the C2-still-running status and all quoted passages were read directly from ReversingLabs’ 6 October 2026 report (John P. Mello Jr.) on 7 October 2026. Underlying detection is attributed to Checkmarx’s Bruno Dias via that report; the Checkmarx primary post was not independently fetched. SecurityWeek’s 22 September 2026 item on the malicious B-tree package is cited as corroborating prior coverage; no download figures are asserted for indexed-btree. The MALFEX, SubQL, and OX references are our own prior coverage, linked inline. We assert no exploitation scope beyond what these sources state.
Sources: