Industrialised Malware Campaigns
- templated look-alike packages around popular toolchains
- dropper-led, credential-first payloads
- registry flooding and repository abuse
- install-time and run-time execution
Scenario
A front-end developer is setting up a new Vite and Tailwind project. A build plugin fails on the latest release, so they search npm for an alternative. They find a package with a plausible name, a copied README and a few thousand downloads. It installs cleanly and the build works.
The package is stage zero. Its install script, or the first require of its entry point, runs a small loader. The loader fetches an encrypted second stage from a URL on a mainstream hosting service. That stage steals browser sessions, ~/.npmrc, .env files, SSH keys and wallet data, then installs a backdoor for later.
The developer did nothing unusual. They added "one more plugin" under deadline, the way everyone does. The attacker had published dozens of near-identical variants, so when one was removed another took its place.
A second version of the same attack arrives through a recruiter. The developer is sent a take-home exercise. The repository depends on one of these packages, and the developer runs npm install and npm run dev to try it out.
Real-world precedent: Sonatype's 2026 State of the Software Supply Chain report counted more than 454,000 new malicious packages in 2025, with over 99% on npm. It linked more than 800 packages that year to North Korea's Lazarus Group, 97% of them on npm, and mapped 341 of them to just 32 "anchor" packages. Socket independently tracked North Korea's Contagious Interview campaign through 338 malicious npm packages by October 2025 and 197 more by late November, delivered through fake job interviews.
Reconnaissance
Explanation
Industrialised campaigns study how developers choose packages, then manufacture packages to fit. Sonatype found that Lazarus naming clusters around Tailwind, Vite, React, Node, Next, ESLint, Webpack, PostCSS and Babel. About 43% of Lazarus-linked packages referenced common developer framework or tool keywords. Sonatype calls this toolchain masquerading: packages posing as framework add-ons, build plugins, linters and migration helpers.
The other half of the reconnaissance is social. Contagious Interview operators pose as recruiters on LinkedIn and job sites, and target Web3 and crypto developers and technical job seekers. The interview repository is the delivery vehicle. Malicious IDE Extensions covers the same campaign hiding commands in .vscode/tasks.json, and Phishing Developers covers the wider pattern of social engineering aimed at developers.
Insight
These campaigns are a production line. Sonatype mapped 341 Lazarus packages to 32 anchors, with the largest anchors fanning out into dozens of variants. Blocking one package name does very little. You need controls that work on the pattern.
Practical
- List the toolchains your teams add plugins to most often. Those are the names attackers imitate.
- Check how a new package gets into a project today. Is there any step between
npm install some-pluginand a commit? - Ask your developers whether they have been sent coding exercises by recruiters, and how they ran them.
Tools/Techniques
- npm search and download statistics, viewed the way a hurried developer sees them.
- Public research feeds on active campaigns: Socket, Sonatype, ReversingLabs, Unit 42, Datadog Security Labs.
Metrics/Signal
- Number of distinct packages added to projects each month.
- Share of new packages in front-end tooling categories (plugins, configs, loaders).
Evaluate
Explanation
Assess where untrusted package code can run, and what it can reach when it does. These campaigns are, in Sonatype's words, dropper-led and credential-first. Sonatype found droppers in about 98% of Lazarus packages and secrets exfiltration in about 64%. About 77% combined two or more threat types.
Code runs at two points: during install (lifecycle scripts) and when the package is first loaded. Both happen on developer laptops and in CI, where tokens are plentiful.
Insight
Most of the volume is noise. Sonatype classed 55.9% of 2025 malware as repository abuse, such as the IndonesianFoods flood of spam packages built to farm TEA protocol rewards. That noise wears out reviewers and scanners, and it hides the smaller number of packages that steal credentials.
Practical
- Check your npm and pnpm versions. npm 12 and pnpm 10 and later block dependency install scripts by default. Older npm versions run them.
- List which projects have approved install scripts, and why.
- Check what credentials exist on developer machines and CI runners that install packages:
~/.npmrctokens, cloud keys, SSH agents, browser sessions. - Check whether your repository manager can quarantine or block packages, or whether it simply proxies everything from the public registry.
npm --version
npm install-scripts ls # npm 12: dependencies with unreviewed install scripts
pnpm ignored-builds # pnpm: builds that were blocked
Tools/Techniques
- npm install-scripts and pnpm build settings.
- OSV-Scanner, which includes malicious package records from the OpenSSF malicious-packages dataset.
Metrics/Signal
- Projects still installing with install scripts enabled for all dependencies.
- Machines that install packages and also hold long-lived publish or cloud credentials.
Fortify
Explanation
Fortify against the pattern, not the package. Block new and unknown packages by default, stop install-time execution, wait out the first days of a release, and install untrusted code somewhere with nothing worth stealing.
Insight
Industrialised campaigns depend on speed. Malicious packages are usually found and removed within days. A short release-age gate and a quarantine step in your repository manager turn that speed against the attacker.
Practical
- Block by default at the repository manager. Configure your proxy or registry firewall to quarantine packages flagged as malicious and to hold brand-new packages until reviewed. Developers and CI must install only through it.
- Keep install scripts off. On npm 12 and pnpm this is the default. Approve scripts per package, pinned to a version. On older npm, set
ignore-scripts=true. - Gate fresh releases. Use npm
min-release-age, pnpmminimumReleaseAgeor RenovateminimumReleaseAge. - Install untrusted code in isolation. Run take-home exercises, unfamiliar repositories and new tools in a devcontainer or disposable VM with no credentials mounted.
{
"allowScripts": {
"esbuild@0.25.10": true
}
}
# pnpm-workspace.yaml
minimumReleaseAge: 4320 # three days, in minutes
allowBuilds:
esbuild: true
# .npmrc (npm 11 and earlier, or as a belt-and-braces setting)
ignore-scripts=true
min-release-age=3
Tools/Techniques
- A repository manager or registry firewall with quarantine and block policies.
- npm
allowScripts,ignore-scriptsandmin-release-age; pnpmallowBuildsandminimumReleaseAge. - Dev Containers or a cloud workspace with no secrets attached.
Metrics/Signal
- Percentage of installs that go through the repository manager.
- Approved install-script entries, each with a named owner.
Limit
Explanation
Assume a lure package runs. Limit what it can steal and how long stolen access stays useful. Blocking install scripts helps, but it is not enough on its own. In the fake-interview flow the victim runs the project, so a loader inside an imported package runs anyway.
Insight
The payload is credential-first. If the machine that ran it holds no publish token, no long-lived cloud key and no logged-in browser for production consoles, the attacker gets far less.
Practical
- Use npm and PyPI trusted publishing from CI, and keep no publish tokens on laptops.
- Use short-lived cloud credentials through SSO or OIDC, not static keys in
~/.aws/credentials. - Keep crypto wallets and production admin sessions off development machines.
- Separate the machine or container that runs interview exercises from the one that holds work access.
Tools/Techniques
- npm trusted publishing and PyPI trusted publishing.
- Cloud SSO with short session lifetimes.
- Disposable VMs or devcontainers for untrusted repositories.
Metrics/Signal
- Long-lived tokens found on developer machines, trending to zero.
- Time to revoke every credential on a machine after a suspected infection.
Expose
Explanation
Detect the second stage. The first-stage package is small and quiet. The loader then fetches a payload, often from legitimate services: Sonatype lists Slack, GitHub, Dropbox, blockchains and logging services being used for command and control, and Socket saw Contagious Interview stage payloads on Vercel.
Insight
A node process that spawns a shell, contacts a new domain or reads ~/.ssh within seconds of npm install or npm run dev is the clearest signal you will get.
Practical
- Monitor outbound network traffic from CI install steps and alert on new destinations.
- On developer machines, use EDR rules for
nodeorpythonspawning shells,curlor PowerShell during installs. - Scan lockfiles daily against malicious package feeds, because packages are often flagged after you installed them.
- Treat a hit as a credential incident: rotate everything the machine could reach.
Tools/Techniques
- StepSecurity Harden-Runner for CI egress baselining on GitHub Actions.
- OSV-Scanner on a schedule against
main. - Endpoint detection with process-tree rules for package managers.
Metrics/Signal
- New egress destinations from install and build steps.
- Time from a malicious package advisory to knowing whether you installed it.
Exercise
Explanation
Rehearse the lure safely. Use a local registry and a harmless package that behaves like a first-stage loader.
Insight
The drill usually shows that the install-script block works and that the run-time path is wide open. That is worth knowing before an attacker shows you.
Practical
- Run a local Verdaccio registry. Publish a harmless package named like a build plugin, for example
vite-plugin-drill-test. - Give it a
postinstallscript and an entry point that each write a marker file to/tmpand print a message. No network calls. - Create a sample "take-home exercise" project that imports it. In a devcontainer pointed at Verdaccio, run
npm install, thennpm run dev. - Record which markers appear. Then add a canary token URL fetch to the entry point and check that egress monitoring alerts.
- Confirm the release-age gate and repository quarantine would have held the package.
Tools/Techniques
- Verdaccio, a devcontainer and Canarytokens.
- Your normal EDR and egress monitoring, configured as in production.
Metrics/Signal
- Which execution points (install, import) your controls blocked.
- Time from the canary fetch to an alert.
Further Reading
- Sonatype: 2026 State of the Software Supply Chain, open source malware chapter
- Socket: Contagious Interview campaign escalates, 338 malicious npm packages
- Socket: Inside the GitHub infrastructure powering Contagious Interview
- Endor Labs: The great Indonesian TEA theft
- npm install-scripts documentation
- See also Shai-Hulud npm Worm, Phishing Developers and Malicious IDE Extensions.