Threat reportSupply ChainTL-2026-2969
indexed-btree npm supply-chain campaign bypasses npm's default-disabled install scripts via runtime prototype hook
indexed-btree npm supply-chain campaign bypasses npm's (TL-2026-2969), also tracked as indexed-btree campaign, is a high-severity supply-chain compromise, first published 2026-10-06. It has no confirmed attribution, affects npm ecosystem (Node.js) indexed-btree and related btree-themed, maps to 17 MITRE ATT&CK techniques (T1027, T1036.005, T1059.007), and is covered by 9 detection rules and 22 indicators of compromise.
- Severity
- HIGHAssessed severity
- CVEs
- 0None referenced
- Techniques
- 17MITRE ATT&CK
- Actors
- 0Not attributed
- Detection rules
- 9SPL · KQL · Sigma
- IOCs
- 22Indicators of compromise
Key facts for TL-2026-2969
- Threat ID
- TL-2026-2969
- Also known as
- indexed-btree campaign, btree npm malware campaign
- Severity
- HIGH
- Status
- ACTIVE
- Category
- SUPPLY_CHAIN
- First published
- Last reviewed
- Attribution confidence
- LOW
- Motivation
- FINANCIAL
- Target sectors
- technology, software-development, finance
- Target regions
- Global
- Detection rules
- 9
- Indicators of compromise
- 22
Malware and tooling in indexed-btree npm supply-chain campaign bypasses npm's
Malware and tooling: EtherHiding loader (indexed-btree)
How indexed-btree npm supply-chain campaign bypasses npm's works
A family of malicious npm packages led by indexed-btree (impersonating sorted-btree) hides its loader in BTree.prototype.set, so it runs when an application uses the library rather than at install time, sidestepping npm 12's default disabling of lifecycle scripts. The payload fingerprints the host, reports to hardcoded Slack and Telegram channels, and pulls an encrypted second stage from an Ethereum Sepolia smart contract (EtherHiding).
Checkmarx Zero (published 2026-09-17) and ReversingLabs (2026-10-06) describe a campaign in which the npm package indexed-btree mimics the legitimate sorted-btree library. Unlike typical npm malware, the package contains no preinstall or postinstall script and has a clean package.json, so it is unaffected by npm 12 (released 2026-07-08), which turns off dependency lifecycle scripts and implicit node-gyp builds by default (allowScripts defaults to off). Instead the loader is embedded in BTree.prototype.set, a core method applications call during normal use. Per reporting, the loader checks whether the key equals 100 and then launches an obfuscated JavaScript file (sharedLoad.min.js) from the package as a detached process, so the payload runs with the full privileges and network access of the host application. The package was backed by cover infrastructure: a GitHub repository (INDEXED-BTREE/indexed-btree) with a plausible commit history and a fabricated developer profile with an AI-generated photograph.
The first-stage loader fingerprints the host (OS/architecture, hostname, CPU, memory; the sibling mutex-forge loader also collects platform, release and uptime) and posts the data to a hardcoded Telegram chat (-1003952553968) and Slack channel (C0B8XPGCKQS) using bot tokens shipped inside the file. It then connects to an Ethereum Sepolia testnet smart contract (0xE390863Dac96a7118C71227C2b099B50cF602D31), using the contract as a pointer/dead-drop for an encrypted second-stage payload, an approach (EtherHiding) that is more resilient to takedown than a conventional C2 domain. Per analysis of the earlier related package mutex-forge, the payload is AES-GCM encrypted with a key derived via ECDH from an X25519 keypair, written to disk and executed, and a persistent command channel is kept by polling the Slack API for attacker commands. Researchers note the same contract and the same Slack/Telegram identifiers appeared in mutex-forge, linking the two clusters.
Scale: indexed-btree reportedly reached about 2 million weekly downloads before detection, and the family of roughly ten related packages (ordered-kv-index, btree-leaderboard, priority-slot-queue, btree-range-store, btree-core, btree-time-index, btree-lru-cache, neighbor-key-map, sliding-score-window) was tied to over 5 million cumulative downloads over roughly eleven weeks. Checkmarx cautions that download counts are not a count of compromised hosts, because execution requires application code to actually call the hooked method. The operator reportedly collected about 109 ETH (about EUR 231,000 / USD 265-300K) through the contract. As of late reporting the campaign was described as ongoing with C2 still operational and the GitHub repository still online; packages were reported removed. No threat actor has been named.
Note: the attacker-embedded Slack and Telegram bot tokens and RPC API keys disclosed by researchers are deliberately not reproduced here; only non-secret identifiers are listed as IOCs.
MITRE ATT&CK techniques used in TL-2026-2969
Defense Evasion
T1027 Obfuscated Files or Information; T1036.005 Match Legitimate Resource Name or Location; T1070.004 Indicator Removal: File Deletion; T1140 Deobfuscate/Decode Files or Information; T1480 Execution Guardrails
Execution
Command and Control
T1071.001 Web Protocols; T1102.002 Bidirectional Communication; T1573.001 Symmetric Cryptography
Discovery
T1082 System Information Discovery
Initial Access
T1195.002 Compromise Software Supply Chain
Exfiltration
T1567 Exfiltration Over Web Service
Resource Development
T1583.006 Acquire Infrastructure: Web Services; T1585.001 Establish Accounts: Social Media Accounts; T1587.001 Malware; T1608 Stage Capabilities
Impact
Affected products and versions in indexed-btree npm supply-chain campaign bypasses npm's
- npm ecosystem (Node.js) — indexed-btree and related btree-themed packages
Vulnerable versions: indexed-btree (all versions); ordered-kv-index; btree-leaderboard; priority-slot-queue; btree-range-store; btree-core; btree-time-index; btree-lru-cache; neighbor-key-map; sliding-score-window
Fixed in: Packages removed from npm; remove and rotate secrets
Remediation for indexed-btree npm supply-chain campaign bypasses npm's
Patches
- No CVE or vendor patch; the malicious packages were reported removed from npm
Immediate actions
- Search lockfiles, SBOMs and node_modules for indexed-btree, ordered-kv-index, btree-leaderboard, priority-slot-queue, btree-range-store, btree-core, btree-time-index, btree-lru-cache, neighbor-key-map, sliding-score-window and mutex-forge (2.0.0-2.0.2)
- Remove the packages and treat any host or CI runner whose application called the library as compromised; rotate secrets reachable from those processes
- Hunt for outbound connections from node processes to api.telegram.org, slack.com (chat.postMessage / API polling) and Sepolia RPC endpoints, and for detached node processes launching sharedLoad.min.js or withLoad.min.js
- Block or alert on the Telegram chat ID -1003952553968, Slack channel C0B8XPGCKQS and contract 0xE390863Dac96a7118C71227C2b099B50cF602D31 where egress inspection permits
Workarounds
- Run untrusted dependencies in sandboxed or egress-restricted environments
- Keep npm 12 allowScripts off, but treat it as one layer only since this campaign does not use lifecycle scripts
Longer-term hardening
- Do not rely on npm's disabled install scripts alone; add runtime behaviour monitoring for dependencies (unexpected network egress, child process spawn, file writes)
- Verify package provenance and review unexpected code changes in dependencies; be skeptical of new look-alike packages with fabricated repository history
- Restrict egress from build and application hosts to required destinations; use allow-listed outbound traffic for Node processes
- Pin and review dependencies, use a private registry or package firewall with malware scanning
Weaknesses (CWE) in indexed-btree npm supply-chain campaign bypasses npm's
Timeline of indexed-btree npm supply-chain campaign bypasses npm's
- npm 12 released with dependency lifecycle scripts (preinstall/install/postinstall) and implicit node-gyp builds disabled by default (allowScripts off).
- OSV publishes MAL-2026-13955 for mutex-forge (2.0.0-2.0.2), the earlier sibling package that shares the Sepolia contract, Slack channel and Telegram chat; its loader triggers in runExclusive when meta.jobId is 'cross-chain-transfer'.
- OSV record MAL-2026-13955 for mutex-forge is modified; it notes a third stage polling Slack every 10 seconds for attacker commands and advises rotating credentials from a clean machine.
- Checkmarx Zero publishes analysis of the indexed-btree campaign and its nine related btree packages, with Sepolia contract, Slack and Telegram IOCs.
- SecurityWeek and DevOps.com report indexed-btree reached ~2M weekly downloads, 5M+ total across the family, ~109 ETH collected; campaign described as ongoing and the fake GitHub repo still up.
- Cloud Security Alliance publishes a research note on npm runtime-execution supply-chain attacks.
- Hive Security publishes analysis stressing that installing or importing the package is not by itself evidence the second stage executed; the payload fires only when BTree.prototype.set is called with key 100.
- ReversingLabs publishes analysis stating npm's default install-script mitigation is already defeated by the indexed-btree runtime prototype hook; C2 infrastructure still operational.
Sources cited for indexed-btree npm supply-chain campaign bypasses npm's
- Dependency installation security measure already defeated on npm (ReversingLabs)
- npm btree malware campaign affects millions of downloads, no need for install script (Checkmarx Zero)
- Malicious B-Tree npm Package Accumulates Millions of Downloads (SecurityWeek)
- New npm Threat Bypasses Install Script Protections (DevOps.com)
- indexed-btree npm malware runtime trigger (Hive Security)
- Malicious npm Package With 2 Million Downloads Hides Malware in Runtime Code (Cryptika)
- npm 12 disables install scripts by default (The Hacker News)
- OSV MAL-2026-13955: Malicious code in mutex-forge (npm)
- CSA research note: npm runtime execution supply chain
Detection coverage for TL-2026-2969
As of 2026-10-06, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2969 across Splunk SPL, Microsoft KQL and Sigma, covering 22 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.