Security Digest · Jul 11, 2026 · Supply-chain compromise · Library

jscrambler npm Compromise: Infostealer in CLI Releases

Five jscrambler npm releases and four plugin versions shipped a Rust infostealer on Jul 11, 2026. Move to 8.22.0+ and rotate secrets if you installed one.

Our verdict

Check exposure

Only builds that installed one of the poisoned versions during a roughly three-hour window on July 11 are at risk, but any machine that did should be treated as compromised.

Who must act: Teams that use the jscrambler CLI or its webpack, gulp, grunt or Metro plugins and installed or updated them on or after July 11, 2026 without a lockfile pinning an older version.

Who can relax: Users of Jscrambler's hosted products only (Webpage Integrity, Iframe Integrity), and projects whose lockfiles pinned jscrambler 8.13.0 or earlier throughout July 11-13.

Affected
jscrambler 8.14.0, 8.16.0, 8.17.0, 8.18.0, 8.20.0
jscrambler-webpack-plugin 8.6.2
gulp-jscrambler 8.6.2
grunt-jscrambler 8.5.2
jscrambler-metro-plugin 9.0.2
Fixed in
jscrambler 8.22.0 and later (8.13.0 and 8.15.0 are also clean)
Current releases of the four plugins
CVSS
Not scored
EPSS
n/a
CISA KEV
Not listed
Exploitation
Exploited in the wild
Severity
Critical

What to do

  1. Search lockfiles and node_modules for the five bad jscrambler versions and the four plugin versions.
  2. Upgrade to jscrambler 8.22.0 or later and reinstall from a clean state, with caches purged.
  3. On any machine or CI runner that installed a bad version, rotate every credential it could reach: cloud keys, npm and GitHub tokens, AI-tool API keys, wallet secrets.
  4. Treat affected developer machines as compromised: check for persistence and reimage if in doubt.
  5. Add a minimum release age (npm min-release-age, pnpm minimumReleaseAge) so brand-new versions are not installed automatically.

How to check if you are affected or compromised

  • grep package-lock.json, yarn.lock and pnpm-lock.yaml for jscrambler 8.14.0/8.16.0/8.17.0/8.18.0/8.20.0 and the four plugin versions listed above.
  • Look for dist/setup.js with SHA-256 a742de963f14a92d24ebcbc7b44ac867e23a20d31d1b0094a13a4f83287f4e60, or a ~7.8 MB dist/intro.js, inside installed jscrambler packages.
  • On affected hosts, look for randomly named hidden executables in the temp directory and new systemd units, crontab entries or macOS LaunchAgents created on or after July 11.

What happened#

On July 11, 2026, an attacker published a malicious jscrambler 8.14.0 to npm at 15:12 UTC, according to the registry metadata. jscrambler is the command-line client for Jscrambler's JavaScript obfuscation service. Socket flagged the release six minutes later and opened issue #322. Over the next three hours the attacker pushed four more malicious versions (8.16.0, 8.17.0, 8.18.0 and 8.20.0) while Jscrambler tried to regain control. The company's postmortem says the first attempt to lock the attacker out revoked the developer's own npm credential. The attacker kept publishing with a separately stolen token until it was found and revoked at 18:12 UTC, when clean 8.22.0 shipped.

Per the postmortem, a Jscrambler developer's machine was compromised. It held a GitHub SSH key and npm publishing credentials. The attacker used write access to the repository and a GitHub Actions workflow to extract the npm token. The company says none of its hosted products, customer data or source code was affected.

The payload, a cross-platform Rust infostealer, is described by Socket and Snyk. A roughly 7.8 MB file disguised as dist/intro.js holds Linux, Windows and macOS binaries. A loader, dist/setup.js, unpacks one to a hidden temp file and runs it. It targets crypto wallets, AI-tool and MCP configurations (Claude Desktop, Cursor, Windsurf, VS Code and others), AWS, GCP and Azure credentials, browser data and chat-app sessions. Socket also reports persistence through systemd, crontab and LaunchAgents.

Who is affected#

Anyone who installed jscrambler 8.14.0, 8.16.0, 8.17.0, 8.18.0 or 8.20.0. On July 13, Jscrambler found four helper packages that depend on the poisoned 8.18.0: jscrambler-webpack-plugin 8.6.2, gulp-jscrambler 8.6.2, grunt-jscrambler 8.5.2 and jscrambler-metro-plugin 9.0.2. Versions 8.13.0, 8.15.0 and 8.22.0 and later are clean. npm counted 1,614 downloads across all affected packages. Jscrambler expects many of those came from security researchers rather than real victims.

Do you really need to act?#

Only if one of those versions actually landed in your environment. The exposure window was short: the bad versions were live on July 11 and npm removed them on July 13. Teams that commit lockfiles and did not update jscrambler during that window were never exposed.

  • 8.14.0, 8.16.0 and 8.17.0 ran the dropper from a preinstall hook, so npm install alone was enough.
  • 8.18.0 and later dropped the hook and injected the dropper into dist/index.js and the CLI entry point. Per Socket, --ignore-scripts does not stop them, because they fire when the CLI runs or the module is imported.
  • CI runners are the most likely victims. The plugins run during builds, and build environments tend to hold deploy keys and cloud credentials.

If a bad version ran, assume every secret on that machine is gone. Upgrading the package does not undo the theft.

What to do now#

  1. Find exposure: npm ls jscrambler jscrambler-webpack-plugin gulp-jscrambler grunt-jscrambler jscrambler-metro-plugin in each project, plus grep -nE 'jscrambler.*8\.(14|16|17|18|20)\.0' package-lock.json yarn.lock pnpm-lock.yaml. Also check CI logs from July 11 to 13.
  2. Upgrade: npm install jscrambler@latest (8.22.0 or later). Then delete node_modules, run npm cache clean --force on shared runners, and reinstall.
  3. Rotate from a clean machine every credential the affected host could read: cloud keys, npm and GitHub tokens, SSH keys, and AI provider keys stored in assistant or MCP configs.
  4. Reimage developer laptops that ran a bad version. The stealer can escalate with sudo and install persistence.
  5. Follow Jscrambler's own lesson and add a cooldown: npm's min-release-age or pnpm's minimumReleaseAge.

How to tell if you were hit#

Inside an installed package, a dist/setup.js with SHA-256 a742de963f14a92d24ebcbc7b44ac867e23a20d31d1b0094a13a4f83287f4e60 or a multi-megabyte dist/intro.js is the tell. Socket lists hashes for the decompressed binaries too. On hosts, look for hidden, randomly named executables in the temp directory, and for systemd units, crontab lines or LaunchAgents created on or after July 11. Then check cloud and GitHub audit logs for use of the credentials that machine held. OSV MAL-2026-10187 lets dependency scanners flag the package automatically.

Timeline#

  • — 15:12 UTC: malicious 8.14.0 published. Socket flags it within six minutes. Clean 8.15.0 follows at 17:07. The attacker publishes 8.16.0, 8.17.0, 8.18.0 and 8.20.0 between 17:26 and 17:53. At 18:12 the stolen token is revoked and 8.22.0 ships.
  • — npm removes the malicious versions. Jscrambler identifies the four plugin versions pinned to 8.18.0.
  • — Jscrambler publishes its postmortem.

Sources

Original sources first: vendor and project advisories, CVE and government records, the discoverers’ write-ups. Every claim above links to one of these. See how the Security Desk works.

Original and primary sources

  1. Jscrambler — Security Incident Postmortem: Malicious Versions of the jscrambler npm Package jscrambler.com
  2. GitHub — jscrambler/jscrambler issue #322: v8.14.0 compromised? github.com
  3. npm registry — jscrambler package metadata registry.npmjs.org
  4. OSV — MAL-2026-10187: Malicious code in jscrambler (npm) osv.dev
  5. Socket — jscrambler npm Package Compromised in Supply Chain Attack socket.dev
  6. Snyk — Embedded Malicious Code in jscrambler (SNYK-JS-JSCRAMBLER-17954275) security.snyk.io