
jscrambler npm package publishes malicious preinstall binary
StepSecurity documents a supply-chain compromise of jscrambler, the official npm CLI for the Jscrambler Code Integrity API, starting with version 8.14.0. A malicious preinstall hook (later inlined into the main module to evade install-script scanners) drops a Rust-compiled, platform-specific native binary (ELF/PE32+/Mach-O) smuggled inside a fake dist/intro.js behind a custom magic header, containing an embedded SQLite/LevelDB parser and BIP39 wordlist consistent with a credential and crypto-wallet stealer. The Linux payload dynamically links libbpf and loads an in-memory eBPF program for kernel-level instrumentation, and all three platform binaries include anti-debugging checks; affected versions (8.14.0, 8.16.0, 8.17.0, 8.18.0, 8.20.0) were interleaved with clean releases, and C2 traffic was observed reaching Tor entry-node infrastructure and two raw IPs.
What it is
jscrambler, the official npm CLI for Jscrambler's Code Integrity API (JS obfuscation/web-app protection service, ~10 maintainers, history back to 0.1.0), was compromised starting with version 8.14.0 (published July 11, 2026). Affected releases: 8.14.0, 8.16.0, 8.17.0, 8.18.0, 8.20.0. The last known clean release before the compromise was 8.13.0 (June 30, 2026); 8.22.0 is confirmed clean. The payload is a Rust-compiled native binary — a cross-platform browser-credential and crypto-wallet stealer, not a downloader.
How it works
A 7.8 MB file disguised as dist/intro.js is not JavaScript — it is a custom container behind a 5-byte magic header (1B 43 53 49 01) holding three gzip-compressed native executables (ELF/PE32+/Mach-O arm64), one per platform. A short, unobfuscated loader selects the entry matching process.platform, decompresses it to a randomly named dotfile in the temp dir, sets the exec bit, and spawns it detached and unref'd so it survives after the parent exits. All attacker logic lives in the compiled binary, which resists static string analysis.
The critical detail: the trigger changed across two generations, but the container is byte-for-byte identical throughout.
flowchart TD A[dist/intro.js container<br/>identical all releases] --> G1 A --> G2 G1[Gen 1: 8.14.0/8.16.0/8.17.0<br/>preinstall hook] -->|npm install| X[loader spawns binary] G2[Gen 2: 8.18.0/8.20.0<br/>inlined IIFE in dist/index.js] -->|any require jscrambler| X X --> Y[credential + wallet stealer]
Gen 2 removes the preinstall script from package.json entirely and inlines the same loader as an IIFE at the top of dist/index.js, so it fires on any require("jscrambler") — a build tool, CI helper, or app using the API programmatically — with no npm install needed. Scanners that only check for install hooks flag these two releases clean.
Static analysis of the binary shows embedded SQLite (FTS3/4 strings, targeting Chrome/Firefox Login Data, Cookies, Web Data, key4.db), LevelDB (Chromium Local Storage / IndexedDB where MetaMask-style wallets store encrypted vaults), and a BIP39 English wordlist (seed-phrase parsing).
Preconditions / Affected
Compromised and clean releases are interleaved, not a contiguous bad range — verify each version individually. A fast tell: unpacked tarball jumps from ~37.8 kB to ~7.9 MB. Gen 2 does not require an install step to fire, only an import.
What to do
If you installed 8.14.0, 8.16.0, 8.17.0, 8.18.0, or 8.20.0: treat the host as compromised. Pin to 8.22.0 or another verified clean version, rotate every credential logged into a browser on that machine, and audit crypto wallet browser extensions for unauthorized activity.
Block/hunt these IOCs (added to StepSecurity's Harden-Runner block list):
archive.torproject.org
check.torproject.org
37.27.122.124
57.128.246.79Caveats
Full disassembly and recovery of the binary's C2 endpoint were still ongoing at time of writing; the observed network endpoints above come from Harden-Runner runtime monitoring, not from recovered strings.
Organisations named here
- OSS AI Package Analyst
Technologies named here
- StepSecurity OSS AI Package Analyst
- jscrambler
- Linux
- Harden-Runner
- Windows
- StepSecurity Secure Registry
- StepSecurity Dev Machine Guard
- macOS
- npm Package Cooldown Check
- @vapi-ai/server-sdk
- NPM Package Compromised Updates Check
- ai-sdk-ollama
- jagreehal package family
- npm Package Search
- StepSecurity Threat Center
- npm
- Rust
- eBPF
- SQLite
- StepSecurity
- Tor
- MetaMask
Techniques named here
- Malicious preinstall hook
- Binary hidden inside fake .js file
- Detached/unref'd process spawning
- Inlining payload into main module
- In-memory eBPF loading
- Generic syscall use to evade import-table detection
- Anti-debugging checks
- TCP connection/process enumeration
- Browser credential store and crypto wallet theft
- Phantom Gyp
Threat actors named here
- Miasma Campaign
- Phantom Gyp technique
- Miasma
Related in Supply Chain


