Skip to main content
PolinRider Used Blockchain to Hide Malware in npm PackageIncident
5 min readFor Security Engineers

PolinRider Used Blockchain to Hide Malware in npm Package

What Happened

Between late 2024 and early 2025, attackers compromised two versions of the npm package @common-stack/generate-plugin (9.0.2-alpha.21 and 9.0.2-alpha.22). The package, which sees over 1,100 weekly downloads, executed malicious code during installation that attempted to retrieve a second-stage payload from the Tron blockchain. Sonatype identified the attack and linked it to the PolinRider APT group.

The attack exploited npm's pre-install hooks. When developers ran npm install, the malicious code executed before they could inspect it. The payload retrieval mechanism used blockchain transactions as a dead drop—a technique that makes takedowns nearly impossible since you can't delete a blockchain entry.

Timeline

Initial Compromise Window: Exact compromise date unknown, but malicious versions were published to npm registry.

Detection: Sonatype's automated scanning identified the malicious code in the package.

Public Disclosure: Sonatype published findings linking the attack to PolinRider APT group.

Response: npm registry removed the compromised versions.

Current Status: Package maintainer has published clean versions; over 1,100 weekly downloads mean potential exposure extends to hundreds of development environments.

Which Controls Failed or Were Missing

No pre-installation package verification: Development teams installed packages without validating their integrity or inspecting their install scripts. The malicious code ran automatically through npm's lifecycle hooks—specifically, the preinstall script that executes before the package is even fully installed.

Missing egress filtering: Developer workstations had unrestricted outbound network access. The malware attempted to connect to blockchain nodes to retrieve its payload. If egress traffic had been filtered to known-good destinations, this connection would have failed.

No dependency pinning: Teams likely used version ranges (^9.0.0 or ~9.0.2) instead of exact versions in package.json. This allowed npm to automatically pull the malicious alpha versions when developers ran fresh installs.

Absent runtime monitoring: No tooling detected the unusual behavior—a build tool making blockchain API calls during installation. Endpoint detection and response (EDR) tools either weren't deployed on developer machines or weren't configured to flag suspicious npm process behavior.

No private registry proxy: Packages flowed directly from the public npm registry to developer machines without inspection. A private registry with automated scanning would have caught the malicious code before it reached any workstation.

What the Relevant Standards Require

PCI DSS v4.0.1 Requirement 6.3.2 mandates that you maintain an inventory of bespoke and custom software, and third-party software components. For organizations in PCI scope, this includes your dependency tree. You need to know what's running in your build pipeline, not just in production.

NIST 800-53 Rev 5 Control SA-12 (Supply Chain Protection) requires organizations to employ anti-counterfeit technologies and processes, and to verify the integrity of software and firmware components. This applies directly to open-source dependencies. You're supposed to verify what you install.

ISO 27001 Annex A.8.31 (Separation of Development, Test, and Production Environments) addresses environment isolation. Developer workstations need the same network segmentation as production systems. Unrestricted internet access from a machine that touches your codebase violates this control.

SOC 2 Type II CC6.6 (Logical and Physical Access Controls) requires you to restrict logical access to data and system resources. When a build tool can reach out to arbitrary blockchain nodes and download executable code, you've failed this requirement. Your CI/CD pipeline needs the same access controls as your application infrastructure.

OWASP ASVS v4.0.3 Section 14.2 (Dependency) specifically calls out the need to verify that all components are free from known vulnerabilities. But this attack demonstrates why CVE scanning isn't enough—the malicious code wasn't a vulnerability in the traditional sense. It was intentional malware in what appeared to be a legitimate package update.

Lessons and Action Items for Your Team

Pin your dependencies to exact versions. Change "@package/name": "^1.2.3" to "@package/name": "1.2.3" in package.json. Use npm ci instead of npm install in CI/CD to enforce the lockfile. This prevents automatic updates from pulling in compromised versions.

Deploy a private npm registry with automated scanning. Tools like Sonatype Nexus Repository, JFrog Artifactory, or Verdaccio sit between your developers and the public registry. Configure them to scan packages before they're available internally. Sonatype specifically blocked these malicious versions with their Firewall product—if you'd been proxying through it, your team never would have seen the compromised package.

Inspect install scripts before running them. Add a pre-commit hook that flags any package with preinstall, postinstall, or install scripts. These scripts execute with the same permissions as your user account. Review them manually or block them entirely unless you have a business justification.

Implement egress filtering on developer workstations. Your developers don't need to connect to Tron blockchain nodes. Create an allowlist of required external services (npm registry, GitHub, your cloud provider) and block everything else. Use DNS filtering as a first layer—services like Cloudflare Gateway or Cisco Umbrella can block known-bad domains without requiring endpoint agents.

Enable EDR on developer machines. This isn't just for production servers. Configure your endpoint security to alert on unusual process trees—specifically, npm or node spawning network connections to non-standard ports or making DNS queries for cryptocurrency-related domains.

Audit your dependency tree weekly. Run npm audit and tools like Snyk or Socket.dev in your CI pipeline. But don't stop at CVE scanning—look for packages with recent maintainer changes, unusual download patterns, or install scripts that weren't there in previous versions. Socket.dev specifically flags supply chain risk indicators beyond known vulnerabilities.

Separate your build environment from your development environment. Don't install production dependencies on the same machine where you read email and browse the web. Use containerized build environments or dedicated build servers. If a package does compromise your build, you've limited the blast radius.

The blockchain dead drop technique is new, but the fundamental failure isn't. You're running untrusted code with your credentials in an environment that can access your source code, your cloud accounts, and your internal network. Treat your development pipeline with the same caution you apply to production.

Topics:Incident

You Might Also Like