RFX-PKG-06
Package Ecosystems
2025

Industrialised Malware Campaigns

Open source malware produced at scale, aimed at developer machines and CI
  • templated look-alike packages around popular toolchains
  • dropper-led, credential-first payloads
  • registry flooding and repository abuse
  • install-time and run-time execution
Reconnaissance
Evaluate
Fortify
Limit
Expose
Exercise

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-plugin and 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: ~/.npmrc tokens, 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

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, pnpm minimumReleaseAge or Renovate minimumReleaseAge.
  • 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-scripts and min-release-age; pnpm allowBuilds and minimumReleaseAge.
  • 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

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 node or python spawning shells, curl or 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

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

  1. Run a local Verdaccio registry. Publish a harmless package named like a build plugin, for example vite-plugin-drill-test.
  2. Give it a postinstall script and an entry point that each write a marker file to /tmp and print a message. No network calls.
  3. Create a sample "take-home exercise" project that imports it. In a devcontainer pointed at Verdaccio, run npm install, then npm run dev.
  4. Record which markers appear. Then add a canary token URL fetch to the entry point and check that egress monitoring alerts.
  5. 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