The official jscrambler npm package, published by the legitimate jscrambler_ account ( [email protected] ), was trojanized on July 11, 2026. Over three hours the attacker published five malicious releases (8.14.0, 8.16.0, 8.17.0, 8.18.0, and 8.20.0), interleaved with clean releases the maintainers appear to have pushed as remediation. Every malicious version carries the same native dropper. It unpacks a platform-matched, Rust-compiled infostealer from a bundled binary container and runs it detached. The stealer targets browser profile data (Chrome, Brave, Edge, Chromium), the Bitwarden browser extension, and Steam sessions, and installs persistence through Windows Task Scheduler and macOS LaunchAgents.
The attacker went further than a normal single-version compromise in two ways. First, they republished the identical payload at 8.16.0 just 19 minutes after a clean 8.15.0 shipped, so the first remediation did not close the credential or CI access. Second, at 8.18.0 they moved the dropper out of the preinstall hook and into the package’s own dist/index.js and dist/bin/jscrambler.js , where it runs when the module is required rather than at install time. A scanner that only flags suspicious install scripts sees nothing.
As of the latest check, latest points to a clean 8.22.0, and 8.14.0, 8.16.0, and 8.17.0 are deprecated as compromised. The two runtime-dropper versions, 8.18.0 and 8.20.0, are still published and not deprecated. No commit, tag, or release for any malicious version exists in the jscrambler GitHub repository , which points to an npm account or CI pipeline compromise rather than a source repository compromise. With roughly 60,000 monthly downloads, the blast radius is significant.
Timeline (2026-07-11, UTC):
Versions 8.19.0 and 8.21.0 were never published.
Indicators of Compromise (IoC):
Jscrambler is a commercial JavaScript protection platform. Their official npm CLI client, published under the jscrambler_ account ( [email protected] ), has ten maintainers, several with @jscrambler.com email addresses.
Version 8.13.0 was published on June 30, 2026, matching a GitHub commit from the same day. Version 8.14.0 appeared on July 11, 2026, with no corresponding GitHub commit, tag, or pull request. The GitHub repo’s latest tag is [email protected] . The attacker published directly to npm, bypassing the project’s normal release workflow.
The other packages in the jscrambler ecosystem ( jscrambler-webpack-plugin , gulp-jscrambler , jscrambler-metro-plugin , grunt-jscrambler ) were not affected. Their latest versions remain on the June 30 release and carry no install hooks.
The only change to package.json between 8.13.0 and 8.14.0 is the addition of a preinstall script:
The dropper itself is 43 lines of clean, readable JavaScript. No obfuscation:
The function name ensureNativeRuntime is social engineering aimed at anyone who might glance at the file. A few details worth noting:
The dist/intro.js file is 7,837,238 bytes (7.5 MB) of raw binary data, not JavaScript despite the .js extension. It uses a custom container format:
Each entry is a gzip-compressed native executable. After decompression:
All three are stripped, Rust-compiled binaries. The Rust toolchain is identifiable from rustls TLS library strings, CRYPTOGAMS crypto module markers, and Rust-standard error handling patterns throughout the binary.
Binary analysis with radare2 confirms the dropped executables are compiled with rustc 1.98.0-nightly (e7815e522 2026-06-04) , run on the Tokio async runtime, and carry a debug symbol path of agent.pdb . The project name “agent” is the attacker’s label for the payload.
The attacker practiced deliberate OPSEC. The PDB path is agent.pdb (relative, no full build directory), the PE timestamp and checksum are both zeroed, there is no Rich header (ruling out the MSVC linker, confirming lld-link ), and all Rust panic source locations are stripped. No Cargo metadata, no .cargo/registry paths, no source file references leak through the binary. The project name “agent” is the only label the attacker left on the payload.
The PDB GUID ( 6976bd1e... ), Linux Build ID ( c05bf7dc... ), and the nightly compiler pin ( e7815e522 , June 4, 2026) are durable fingerprints. If this toolchain surfaces in another compromise, these values tie the builds together.
The binaries are not simple credential harvesters. They implement a streaming C2 protocol, cloud secrets theft, browser data extraction, and Electron app targeting.
All three platform binaries contain the same JSON message protocol for real-time command execution:
The "t":"out" messages stream command output back to the operator with progress tracking. "t":"done" signals completion. This is a bidirectional RAT protocol, not one-way exfiltration.
The binaries construct AWS Signature Version 4 authentication headers and call AWS Secrets Manager and SSM Parameter Store APIs:
The WithDecryption: true flag requests plaintext values for encrypted parameters. The binary uses stolen AWS credentials from the compromised machine to access cloud secrets, expanding the blast radius from the local machine to any AWS infrastructure those credentials can reach.
A nested Vault response parser appears in all three binaries:
This matches the structure of Hashicorp Vault’s v1/secret/data/ API responses, where the data field contains the secret payload. The binary can extract secrets from Vault instances accessible with stolen tokens.
The Windows binary targets four Chromium-based browsers by reading their profile directories:
An embedded SQLite engine reads browser databases directly (Login Data, Cookies, Web Data). Full FTS (full-text ) CREATE TABLE statements are present, indicating the binary indexes and searches extracted data. A compiled-in LevelDB reader ( leveldb.BytewiseComparator , .ldb , MANIFEST- ) handles browser local storage and extension data.
The Bitwarden browser extension ID is hardcoded in the Windows binary:
This is Bitwarden’s official Chrome Web Store identifier. The binary reads the extension’s LevelDB local storage.
Steam session cookies appear as a contiguous string in all three binaries:
These cookies grant full account access without credentials.
The binaries contain an ASAR archive parser:
ASAR is the archive format used by Electron applications. This means the payload can extract data from Discord, Slack, VS Code, and other Electron-based desktop apps by reading their archived application data.
The C2 endpoints are not visible in plaintext. The Windows binary contains an 80KB (81,920 bytes, 16-byte aligned) encrypted data blob in the .rdata section starting at offset 0x326400 . Every 4KB block in this region exceeds 7.9 bits of entropy. The blob is not ASN.1 (ruling out CA certificates) and does not respond to single-byte XOR.
The binary includes AES-NI hardware instructions (263 aesenc / aesdec / aeskeygenassist call sites in the Linux ELF), PBKDF2, and scrypt key derivation strings, which suggests the configuration is decrypted at startup from a key derived from a hardcoded passphrase. Recovering the C2 addresses without dynamic analysis is not feasible.
The macOS binary contains the clearest view of the HTTP templates used for C2 communication. Values like host, bearer token, and cookie are filled at runtime from the decrypted configuration:
The raw ws2_32.dll Winsock imports (no WinHTTP/WinINet) confirm the binary handles TCP connections and TLS (via embedded rustls) directly, bypassing system HTTP libraries that might be monitored.
The Linux binary contains a tokenized copy of the dropper’s own JavaScript source code, embedded in the .rodata section. The import chain and the String.fromCharCode evasion technique are both present:
The 2===1 is the tokenized form of platform === 1 (the Windows platform check). The template is parameterized with \xc0XX placeholder tokens where variable names and string literals should be. This is a code generation template: the binary can emit new copies of the dropper with fresh variable names, potentially to inject into other npm packages or JavaScript projects on the compromised machine. The presence of the ASAR parser alongside this template raises the possibility that the payload can trojanize Electron applications by injecting the dropper into their archived source code.
Windows: Task Scheduler. The Windows binary contains a full Task Scheduler XML template:
The task is hidden, runs with an unlimited execution time, and restarts every minute up to 999 times if it fails. cmd.exe execution strings confirm it can run shell commands.
macOS: LaunchAgent. The macOS binary contains a LaunchAgent plist template:
RunAtLoad and KeepAlive with a 30-second StartInterval ensures the binary restarts on login and relaunches if killed.
Linux: BPF capabilities. The Linux binary links against libbpf.so.1 , the BPF (Berkeley Packet Filter) library used for kernel-level network and tracing operations. It also reads /proc/self/mountinfo and /proc/self/cgroup for container and environment detection.
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
