Back to writing
Javascript · AI · Claude

The jscrambler npm hack drops a stealer that hunts your AI tool keys

/ / / 8 min read

jscrambler 8.14.0 shipped a preinstall hook that runs a Rust infostealer during npm install. It goes after AWS, wallets, and your Claude/Cursor/MCP config. What to do.

On this page

Installing one npm package version was enough to get robbed. No import. No CLI call. Just npm install.

On July 11, version 8.14.0 of the jscrambler npm package shipped with a malicious preinstall hook. Pull the package in and it drops a native infostealer onto your machine and runs it, one build for Windows, one for macOS, one for Linux. Socket flagged it six minutes after publish. If your machine or a build runner grabbed it in that window, the payload already ran with whatever access your install had.

Here's why this one is worth your attention even if you've never touched jscrambler: the stealer goes straight for developer secrets, and it's one of the first I've seen that reads the config files for AI coding tools. Claude Desktop, Cursor, Windsurf, Zed. That's where your API keys and MCP credentials live.

Let me walk through what happened, how to check if you're hit, and what to rotate.

What actually landed on the machine

The compromise is two files, both new in 8.14.0 and neither present in the previous release, 8.13.0. The package diff shows them under dist/: setup.js, a small loader, and intro.js. The name is a lie. intro.js isn't JavaScript. It's a roughly 7.8MB blob holding three gzip-compressed native binaries, one per operating system.

On install, setup.js picks the binary for your OS, writes it under a random name in the system temp directory, marks it executable, and launches it detached with its output hidden. You see nothing.

None of this is in jscrambler's public source. StepSecurity and SafeDep both pulled the release apart and found no matching commit, tag, or pull request for 8.14.0. The GitHub repo's latest tag is still 8.13.0. Someone pushed 8.14.0 straight to npm under a legitimate maintainer account, skipping the project's normal release flow. That points to a compromised npm account or a compromised build pipeline. Which one isn't confirmed yet.

The payload is a shopping list of developer secrets

Socket's analysis identifies the binary as a Rust infostealer, built for all three platforms, that sweeps the machine and ships what it finds to a drop server over TLS. The target list reads like an inventory of a working developer's laptop:

  • Cloud credentials from AWS, Azure, and Google Cloud, including the metadata endpoints CI runners use
  • Crypto wallets and seed phrases from MetaMask, Phantom, and Exodus, plus the Bitwarden vault
  • Browser-stored passwords and cookies, and Discord, Slack, Telegram, and Steam sessions
  • Config files for AI coding tools: Claude Desktop, Cursor, Windsurf, VS Code, and Zed, where API keys and Model Context Protocol server credentials tend to sit

That last one is the part I'd flag hardest. A year ago a stealer wouldn't have known to look there. Now your AI tooling is a credential store worth raiding, and attackers have caught up. If you run local MCP servers with keys in a config file, that file is a target now. Worth thinking about how you store those. I wrote a bit about how much these tools hold in how I run Claude Cowork and Obsidian as my second brain, and the flip side is that a rich local setup is a rich thing to steal.

It doesn't stop at file reads. On Linux the payload links the kernel's BPF library and can load an eBPF program into the kernel from memory, which is a foothold in the kernel itself, not the userspace file grabbing the rest of it does. What the eBPF does is still being worked out. The Windows and macOS builds add anti-debugging checks and wire in persistence: a hidden Windows scheduled task that relaunches every minute, and a macOS LaunchAgent that reloads on login. Its command-and-control details stay encrypted in the binary. StepSecurity's runtime monitoring caught it reaching two hard-coded IPs and Tor infrastructure.

Why a build tool is the perfect host

jscrambler is a build-time tool. You install it as a dev dependency or run it from CI. Think about where that puts the stealer: the exact environment it was built to rob. Cloud keys, deploy tokens, source code, all the things a build process can reach, all sitting right there.

The package pulls about 15,800 downloads a week. That's small next to the big npm compromises of the past year that move billions of downloads a week. But reach was never the point here. A stealer aimed at build machines doesn't need volume. It needs access, and CI is access.

This isn't a one-off. It fits a run of npm supply-chain attacks going back to late 2025: the Shai-Hulud worm that spread through hundreds of packages from an install hook, the chalk and debug takeover through a phished maintainer account, and a hijacked account pushing a cross-platform trojan into Axios (83 million weekly downloads). If you want the pattern for spotting this class of attack more broadly, I broke down a related one in 10,000 fake GitHub repos are pushing malware, here's how to spot one.

The timing is almost funny

npm had just moved against this exact attack route. npm 12 shipped on July 8, three days before this release, with dependency install scripts off by default. On npm 12, a preinstall hook like this one doesn't run unless someone approves it. The fix was already out the door.

The catch: older clients still run install scripts automatically. So the protection only helps the people who upgraded. Everyone still on an older npm, and every pipeline pinned to one, runs the payload as before.

And 8.14.0 was never pulled. Version 8.15.0 has since replaced it at the top of npm's list, published from the same maintainer account, clean, no install script, no bundled binary. But 8.14.0 is still live on npm. Any lockfile or command pinned to it keeps installing the stealer. Only the main CLI package was hit. The jscrambler plugins for webpack, gulp, Metro, and grunt stayed on their clean June releases.

What to do now

Three steps, in order.

Get off 8.14.0. Move to 8.15.0, or pin to 8.13.0 for a release from before the incident. Then clear jscrambler@8.14.0 out of lockfiles and caches, because a stale pin will happily reinstall it.

Work out whether you ran it. Check lockfiles and package-manager logs for jscrambler@8.14.0, and CI records from July 11 onward for any run of dist/setup.js. There's no fixed binary name to grep for, since the loader drops its payload under a random name in temp. Line up install timestamps against Node child processes and temp-directory execution instead. On Windows, check Task Scheduler for hidden tasks. On macOS, look in ~/Library/LaunchAgents for plists you don't recognise. This same "check what your dependency manager actually did" instinct is why I changed how I run updates, which I wrote up in composer update is now a security risk, here is the safer workflow.

If it ran, assume the secrets are already gone. Not exposed. Gone. Rotate cloud keys, npm and GitHub tokens, and your AI-tool and MCP API keys. Revoke Discord, Slack, browser, and Bitwarden sessions. Move any crypto off wallets on that host. Block the two C2 IPs below. A stealer does its work in the seconds after install, so by the time you're reading the alert, the theft is done. Rotation is the only honest response.

If you run a team or a client's infrastructure, this is also the nudge to lock down what your build can reach in the first place. Scoped tokens, short-lived CI credentials, and secrets that aren't sitting in plaintext config. My self-hosted security checklist covers the basics of shrinking that blast radius.

Indicators of compromise

Malicious package: jscrambler@8.14.0.

SHA-256 hashes:

  • dist/setup.js: a742de963f14a92d24ebcbc7b44ac867e23a20d31d1b0094a13a4f83287f4e60
  • dist/intro.js: a41a523ef9517aab37ed6eea0ec881821bdcb7aefcb5c5f603adc7907f868c86
  • Linux payload: fbbcf4d8f98168f78f5c0c47a9ae56d59ec8ac84a7c9ca6b797fedfb8d62d2bd
  • Windows payload: b7ca95d1b23c8e67416a25cedf741de0917c2096bbc9d24649eea7853d054903
  • macOS payload: c8fd47d36bdf7c825378593ab82ed8c24d1dc52e26b507812393e24e1d5201fd

Network endpoints:

  • C2 IP: 37.27.122.124
  • C2 IP: 57.128.246.79
  • Tor infrastructure: check.torproject.org, archive.torproject.org

On-host artifacts: a randomly named hidden file in the system temp directory (.{random}, or .{random}.exe on Windows), plus a hidden Windows scheduled task or a macOS LaunchAgent for persistence.

Frequently asked questions

Is the jscrambler npm package safe to use? Only version 8.14.0 is compromised. It shipped a malicious preinstall hook that drops a Rust infostealer during install. Move to 8.15.0 (clean, same maintainer) or pin to 8.13.0 from before the incident. Clear jscrambler@8.14.0 from every lockfile and cache, because 8.14.0 is still live on npm and any pin to it keeps installing the payload.

How do I know if I installed jscrambler 8.14.0? Search your lockfiles and package-manager logs for jscrambler@8.14.0, and check CI records from July 11 2026 onward for any run of dist/setup.js. The payload is written under a random name in the temp directory, so there's no fixed filename to grep. Line up install timestamps against Node child processes and temp-directory execution instead. On Windows check Task Scheduler for hidden tasks; on macOS check ~/Library/LaunchAgents for unfamiliar plists.

What did the jscrambler infostealer actually steal? Cloud credentials from AWS, Azure, and Google Cloud, including CI metadata endpoints. Crypto wallets and seed phrases from MetaMask, Phantom, and Exodus, plus the Bitwarden vault. Browser passwords and cookies, and Discord, Slack, Telegram, and Steam sessions. It also reads config for AI coding tools including Claude Desktop, Cursor, Windsurf, VS Code, and Zed, where API keys and MCP server credentials sit.

Does npm 12 protect me from this attack? Mostly. npm 12 shipped on July 8 2026 with dependency install scripts off by default, so a preinstall hook like this one won't run unless someone approves it. Older npm clients still run install scripts automatically, so a build pinned to 8.14.0 on an old client still runs the stealer.

What should I rotate if jscrambler 8.14.0 ran on my machine? Treat every secret the process could reach as stolen, not just exposed. Rotate cloud keys, npm and GitHub tokens, and AI-tool and MCP API keys. Revoke Discord, Slack, browser, and Bitwarden sessions. Move any crypto off wallets on that host. Block the two C2 IPs (37.27.122.124 and 57.128.246.79).

What to do now

Check your lockfiles for jscrambler@8.14.0 today, even if you think you're clean, because a transitive pin can pull it in without you asking. Bump to 8.15.0, purge the caches, and if it ever ran on a build box, rotate everything that box could touch. The supply chain is only as safe as the last package you didn't read, and that's true whether you're one dev or running a client's whole pipeline.

If your team needs a hand hardening a build pipeline or working out whether a compromise reached anything that matters, that's the kind of thing I help with.

FAQ

Frequently asked

Only version 8.14.0 is compromised. It shipped a malicious preinstall hook that drops a Rust infostealer during install. Move to 8.15.0 (clean, same maintainer) or pin to 8.13.0 from before the incident. Clear jscrambler@8.14.0 from every lockfile and cache, because 8.14.0 is still live on npm and any pin to it keeps installing the payload.

Search your lockfiles and package-manager logs for jscrambler@8.14.0, and check CI records from July 11 2026 onward for any run of dist/setup.js. The payload is written under a random name in the temp directory, so there's no fixed filename to grep. Line up install timestamps against Node child processes and temp-directory execution instead. On Windows check Task Scheduler for hidden tasks; on macOS check ~/Library/LaunchAgents for unfamiliar plists.

Cloud credentials from AWS, Azure, and Google Cloud, including CI metadata endpoints. Crypto wallets and seed phrases from MetaMask, Phantom, and Exodus, plus the Bitwarden vault. Browser passwords and cookies, and Discord, Slack, Telegram, and Steam sessions. It also reads config for AI coding tools including Claude Desktop, Cursor, Windsurf, VS Code, and Zed, where API keys and MCP server credentials sit.

Mostly. npm 12 shipped on July 8 2026 with dependency install scripts off by default, so a preinstall hook like this one won't run unless someone approves it. Older npm clients still run install scripts automatically, so a build pinned to 8.14.0 on an old client still runs the stealer.

Treat every secret the process could reach as stolen, not just exposed. Rotate cloud keys, npm and GitHub tokens, and AI-tool and MCP API keys. Revoke Discord, Slack, browser, and Bitwarden sessions. Move any crypto off wallets on that host. Block the two C2 IPs (37.27.122.124 and 57.128.246.79).

Enjoyed this? Start a project.

Start a conversation →