Skip to content

Back to the catalog

NPM Isn't Prepared For North Korean PolinRider Attack
opensourcemalware.comwriteup

NPM Isn't Prepared For North Korean PolinRider Attack

OpenSourceMalware's case study on npm packages fetch-page-assets and html-to-gutenberg, maintained by a legitimate developer (DiogoAngelim) whose GitHub account was compromised by the DPRK-linked PolinRider campaign in March 2026. The post shows GitHub server-side push timestamps proving all seven of the maintainer's repos were force-pushed with an identical NullReceiver loader in two coordinated bursts, and that after npm pulled the flagged v1.2.9 (GHSA-vxq2-vhm7-7mhq), every subsequent release (v1.2.10-v1.2.14) kept shipping the same .vscode/tasks.json auto-run trigger, with the attacker later adding a second obfuscated payload appended to babel.config.cjs. It argues npm/GitHub's per-version advisory model can't scale against thousands of PolinRider-compromised maintainers and lists specific IOCs (hashes, C2 wallet, RPC endpoints).

TL;DR Case study showing how DPRK's PolinRider campaign kept shipping malware through a compromised npm maintainer's packages for months after a takedown, exposing npm's version-by-version advisory model as unable to scale.
Document

What it is

A case study of PolinRider, a DPRK-linked supply-chain campaign, told through one real victim maintainer: Diogo Angelim (GitHub digelo, npm digelim), a legitimate developer since February 2016. Their npm packages fetch-page-assets and html-to-gutenberg were flagged by JFrog in June (versions fetch-page-assets v1.2.9 and html-to-gutenberg v4.2.11), pulled by npm — and yet, as of the post's writing, the latest release still carried a live DPRK payload.

How it works

The malware hides obfuscated JavaScript inside a compromised developer's build/config files, which auto-execute during local development. Beyond the files the summary lists, the page names postcss.config.mjs, App.js, and babel.config.cjs as carriers. Because the payload lives in the maintainer's local environment and repos, each new npm release the victim publishes re-ships the malware. npm's takedown removes one tarball; the mechanism survives and reproduces on the next publish.

The failure loop

This is the reason the document exists — the compromise persists because the response model is per-version:

flowchart TD
    A[Maintainer env compromised] --> B[Publishes package]
    B --> C[Flagged / advisory issued]
    C --> D[npm takes down that exact version]
    D --> E[Maintainer removes visible symptom]
    E -->|misses underlying mechanism| B

Preconditions / Affected

Individual developer accounts (not organizations) that both got PolinRider-infected and publish/contribute to npm. Confirmed footprint: 4,367 repositories across 2,152 owners as of the July hunt — a 6.5x increase since March, with vendors suggesting the true count reaches the hundreds of thousands.

What to do

The page gives no commands, but two actionable takeaways:

  • A single-version takedown does not clear this. Audit subsequent releases from any maintainer flagged for compromise, not just the flagged version.
  • Detect coordinated force-push bursts via server-side GitHub Events push timestamps (which the attacker cannot backdate). In this case all seven non-archived repos were repointed in two bursts — seven repos in 56 seconds on 2026-07-31, and again in 30 seconds on 2026-08-23.

Caveats

The 4,367/2,152 figure is described by the authors themselves as a floor; the "hundreds of thousands" scale is unverified third-party estimate.

Organisations named here

  • DiogoAngelim
  • GHSA-vxq2-vhm7-7mhq
  • NullReceiver

Technologies named here

  • npm
  • fetch-page-assets
  • html-to-gutenberg
  • GitHub Security Advisory Database
  • @lambda-platform/lambda-vue
  • Dependabot
  • npm audit
  • @syncraft-labs/core
  • @syncraft-labs/react
  • Snyk
  • @syncraft-labs/vue
  • Socket
  • GitHub code scanning
  • DiogoAngelim GitHub account and repositories
  • jsdelivr CDN
  • npm registry ecosystem
  • OpenSourceMalware.com
  • Go and Packagist ecosystems
  • JFrog security research team
  • GitHub
  • GitHub Actions
  • VS Code
  • Node.js
  • Ethereum

Techniques named here

  • Malicious VS Code auto-run task
  • Fake font file payload
  • Malicious code injection into legitimate config files
  • Commit metadata/timestamp forgery
  • Coordinated account-wide force-push bursts
  • CI/build-pipeline lifecycle script injection
  • Blockchain-based C2

Threat actors named here

  • PolinRider
  • NullReceiver
  • DPRK threat actors
  • DPRK