# ChainDrop npm Worm and PolinRider DPRK-Linked Operation Use Blockchain C2 to Steal Cloud and CI/CD Credentials

> ChainDrop is a Shai-Hulud-lineage self-propagating npm worm that compromised 400+ packages (including keyv and cacheable-request) and steals npm/GitHub tokens, SSH keys, cloud, Kubernetes and CI/CD OIDC credentials, resolving its C2 through an Ethereum smart contract. PolinRider is a DPRK-linked (Contagious Interview / Famous Chollima) multi-ecosystem operation that hides obfuscated JavaScript loaders in repository config files and fake .woff2 fonts and resolves payloads from TRON, Aptos and BSC dead drops.

- **Published:** 2026-10-10T00:00:00Z
- **Last reviewed:** 2026-10-10T00:00:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-3214
- **ID:** TL-2026-3214
- **Severity:** HIGH
- **Category:** SUPPLY_CHAIN
- **Status:** ACTIVE
- **Actor:** PolinRider (North Korea)
- **Detections:** 9 · **IOCs:** 30 (full data via the Threadlinqs MCP server — Purple tier)

## Description

ChainDrop (Unit 42, Elastic Security Labs, Aug 2026) is a cross-platform npm worm sharing code lineage with Shai-Hulud (PBKDF2 decoder, Bun 1.3.13 runtime, _NODE_RUNTIME_INIT pattern, npm self-propagation). On 2026-08-04 the maintainer of keyv was compromised and every subpackage of the keyv monorepo was backdoored with a setup.mjs dropper delivered through a package.json preinstall hook. The dropper downloads a Bun runtime and launches an obfuscated credential harvester (Math_Symbol.js in the keyv monorepo, math_init.js in worm-propagated packages). Over 400 unique npm packages were affected, including keyv (600M+ monthly downloads), flat-cache (~580M), cacheable-request (137M+), cacheable (30M+) and cache-manager (16M+). New malicious versions were published within 6-70 minutes of each compromise.

The payload is obfuscated in three layers (Base91 with per-function alphabets and array rotation; a PBKDF2-SHA256 byte-permutation cipher; AES-256-GCM+gzip blobs holding helpers, persistence installers, a memory scraper and workflow templates). It exits silently on Russian locale. It harvests AWS/Azure/GCP/Alibaba credentials, npm and GitHub tokens, SSH keys, Docker/Helm/Git configs, Vault tokens, Kubernetes service-account tokens and kubeconfigs, Terraform state, Jenkins credentials, .env/.netrc files, crypto-wallet files, shell histories and AI coding tool configurations. On GitHub Actions runners it parses /proc/<pid>/mem of Runner.Worker to extract ephemeral OIDC tokens and secrets. Loot is gzip-compressed, AES-256-GCM encrypted with a key RSA-wrapped under an attacker public key, and sent to a C2 endpoint (/router) whose domain is read at runtime from the Ethereum StringListStore contract 0xE1f2395ee43e45A1556EC6438a88c31B83493103 (EtherHiding), with GitHub commit-message markers as a fallback channel and public victim-owned exfiltration repositories (description 'Shai-Hulud: Here We Go Again', Dune-themed names). The worm propagates only when it finds an npm token with package write permission that can publish without 2FA; in the opensearch-js path it abuses GitHub Actions OIDC trusted publishing to mint genuine Sigstore provenance for a malicious dependency (@opensearch/setup). Persistence is planted into project and IDE automation: .vscode/tasks.json (folderOpen), .claude/settings.json (SessionStart hook), .claude/setup.mjs and .vscode/setup.mjs, committed to up to 50 branches per accessible repository as claude@users.noreply.github.com with message 'chore: update config'. Attribution is unclear (TeamPCP adaptation or a separate group reusing the published Shai-Hulud toolkit).

PolinRider (OpenSourceMalware, Socket, Unit 42) is a DPRK-linked operation tied to the Lazarus / Contagious Interview / Famous Chollima cluster (Unit 42 links it to Alluring Pisces). It was disclosed 2026-03-08 with 675 repositories and grew to 1,951 repositories across 1,047 owners by April 2026, later spreading to Go modules (80+), Packagist (10 packages) and npm (162 malicious artifacts across 108 packages by July 2026), with PyPI repositories and Chrome extensions also affected. Obfuscated JavaScript loaders (four-layer string shuffling; markers rmcej%otb% and later Cot%3t=shtP) are appended to config files (postcss.config.mjs, tailwind.config.js, eslint.config.mjs, next.config.mjs, vite.config.js), hidden in fake .woff2 font files, or launched by .vscode/tasks.json with runOn folderOpen fetching from Vercel-hosted bootstrap hosts. Next-stage payloads are fetched from blockchain dead drops (TRON, Aptos, Binance Smart Chain; TxDataHiding and NullReceiver techniques), XOR-decrypted and run via eval() in detached Node processes. Propagation and anti-forensics use temp_auto_push.bat to rewrite git history with anti-dated commits and force-pushes, and compromised maintainer accounts (e.g. Xpos587, 2026-06-23) were used for bulk module poisoning. Weaponized interview templates (ShoeVista via tailwindcss-style-animate, StakingGame) deliver the chain. Follow-on payloads are BeaverTail loader and InvisibleFerret (tracked as DEV#POPPER RAT) and OmniStealer, which steal credentials, browser data and wallet information.

## MITRE ATT&CK

- T1583.001 Domains
- T1195.002 Supply Chain Compromise: Compromise Software Supply Chain
- T1195.001 Supply Chain Compromise: Compromise Software Dependencies and Development Tools
- T1078.004 Valid Accounts: Cloud Accounts
- T1059.007 Command and Scripting Interpreter: JavaScript
- T1059.004 Command and Scripting Interpreter: Unix Shell
- T1204.002 User Execution: Malicious File
- T1546 Event Triggered Execution
- T1027 Obfuscated Files or Information
- T1036.005 Masquerading: Match Legitimate Resource Name or Location
- T1070.006 Indicator Removal: Timestomp
- T1552.001 Unsecured Credentials: Credentials In Files
- T1552.004 Unsecured Credentials: Private Keys
- T1528 Steal Application Access Token
- T1003.007 OS Credential Dumping: Proc Filesystem
- T1555.003 Credentials from Password Stores: Credentials from Web Browsers
- T1005 Data from Local System
- T1568 Dynamic Resolution
- T1071.001 Application Layer Protocol: Web Protocols

## Sources

- [ChainDrop and PolinRider Use Blockchain C2 to Steal Cloud and CI/CD Credentials (GBHackers)](https://gbhackers.com/chaindrop-and-polinrider-malware/)
- [ChainDrop: Inside a Self-Propagating npm Worm (Unit 42)](https://unit42.paloaltonetworks.com/chaindrop-npm-worm-analysis/)
- [Shai-Hulud strikes again: CHAINDROP worm hits 400+ npm packages (Elastic Security Labs)](https://www.elastic.co/security-labs/shai-hulud-chaindrop-npm-supply-chain)
- [Web3 Cloud Supply Chain Attacks (Unit 42)](https://unit42.paloaltonetworks.com/web3-cloud-supply-chain-attacks/)
- [OpenSourceMalware PolinRider technical dossier](https://github.com/OpenSourceMalware/PolinRider)
- [PolinRider Jumps the Fence to Go, Packagist, npm, PyPI (OpenSourceMalware)](https://opensourcemalware.com/blog/polinrider-jumps-the-fence)
- [North Korea Expands the Reach of PolinRider Supply Chain Attack Campaign (DevOps.com)](https://devops.com/north-korea-expands-the-reach-of-polinrider-supply-chain-attack-campaign/)
- [North Korea-Linked Hackers Hide JavaScript Loaders in Open Source Repositories](https://cybersecuritynews.com/north-korea-linked-hackers-hide-javascript-loaders/)
- [ChainDrop: The Keyv and Cacheable npm Supply Chain Attack (Integrity360)](https://insights.integrity360.com/threat-advisories/chaindrop-the-keyv-and-cacheable-npm-supply-chain-attack)
- [Shai-Hulud Returns: ChainDrop Worm Hits npm (OPSWAT)](https://www.opswat.com/blog/shai-hulud-returns-chaindrop-worm-hits-npm-infecting-hundreds-of-packages)
- [Hackers Compromise GitHub Maintainer Accounts to Publish PolinRider-Infected Package Versions (GBHackers)](https://gbhackers.com/github-maintainer-accounts/)

## Full data

Detection queries (Splunk SPL / Microsoft KQL / Sigma) and IOC values require the Threadlinqs MCP server (Purple tier): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-3214
