How Araptus' PNPM Security Scanner Caught Malware in My Dependencies
Self-hosting Araptus' PNPM Supply Chain Security Scanner led to discovering protest-ware hiding in transitive dependencies—before it reached production.
It Started With a Message
A few days ago, Kris from Araptus shared something with me: he'd just released an open-source npm security scanner and blogged about it. The tool was inspired by the Shai-Hulud worm—a self-replicating malware that infected 187+ npm packages with over 2 million weekly downloads back in September.
"Hey, if you have any ideas on how to evolve this, let me know," he said.
I had a few ideas.
Adding Deep Scanning and a Web UI
Kris's original scanner checked direct dependencies in package.json. That's useful, but most supply chain attacks hide in transitive dependencies—the packages your packages depend on. You never installed them directly, so you might not even know they exist.
I contributed the deep scanning capability—analyzing lock files to scan transitive dependencies. This was the key feature that would later catch the malware. I pushed the changes to Kris for review, then built the self-hosted web UI while the pull request was still open.
Analyzes lock files (pnpm-lock.yaml, package-lock.json, yarn.lock) to scan the entire dependency tree—showing dependency chains so you can trace exactly how malicious packages entered your project. This was the feature that caught the malware.
I built the self-hosted web UI—a drag-and-drop interface with animated scan progress, real-time package counters, expandable issue cards, and one-click copy for remediation commands. Built with Astro 5 + React 19, the UI is designed to be self-hosted on your own infrastructure. I implemented it to my home server using my fork with the deep scanning feature, which is what led to discovering the malware.
After I discovered the malware and documented additional findings, Kris merged both contributions into the repository. The deep scanning capability was what caught the malware, and the self-hosted UI made it easy to run scans across all my projects.
Self-Hosting the UI
The web UI is designed to be self-hosted—giving you full control over your security scanning infrastructure. After implementing the UI to my home server infrastructure, I decided to run the scanner across all my Node.js projects. I've been consolidating my development infrastructure lately—centralizing repositories, improving security posture. This seemed like the perfect opportunity to test the scanner in a real-world environment.
I set up automated scanning to run daily across all my Node.js projects. The first scan covered about 15 repositories.
14 came back clean. One didn't.
The Finding
The scanner flagged es5-ext in a web application I was working on. This was code that was about to go into production.
What is es5-ext?
es5-ext is a utility package that, in March 2022, had code added to check if your system locale is Russian or Belarusian—and if so, displays a political message about the Ukraine war. While not destructive like some malware, it executes arbitrary code based on locale detection without user consent. It's classified as protest-ware.
The deep scanning feature I'd just added is what caught it. The package wasn't a direct dependency—it was buried three levels deep:
And here's the kicker: memoizee was never even used in the codebase. Someone had installed it at some point, tried it, abandoned it, and never removed it. An unused dependency brought protest-ware into the project.
Five Minutes to Remediate
Once I knew the issue, the fix was straightforward:
The lock file diff: -294 lines of transitive dependencies removed. The code never made it to production.
The Takeaway
This wasn't a sophisticated attack. It wasn't a zero-day. It was a known protest-ware package that had been sitting in the dependency tree for probably years, just waiting to potentially cause confusion or compliance issues.
I only found it because:
- 1Kris built and shared a tool with me
- 2I added deep scanning to catch transitive dependencies
- 3I decided to run it across everything when setting up new infrastructure
Without that chain of events, this would have shipped to production. I would never have known—until maybe a security audit flagged it, or a Russian-locale user reported unexpected behavior.
What Else the Scanner Has Caught
The scanner has also caught other notable real-world detections that show why deep transitive scanning matters:
node-ipc: The Destructive Protest-Ware
Unlike es5-ext's console messages, node-ipc v10.1.1 was destructive. It detected Russian/Belarusian IP addresses and overwrote files with heart emojis. This affected Vue CLI, Unity Hub, and over a million weekly downloads.
Remediation: Updating @vue/cli to the latest version removes the entire malicious chain.
rc: The Abandoned Author Threat
The rc package was never directly sabotaged, but its author (Marak) demonstrated willingness to destroy his own packages when he sabotaged colors and faker. Since then, rc has been abandoned and flagged—but it has no CVE, so npm audit doesn't catch it.
Remediation: Updating the parent vercel package to v50+ removes the vulnerable chain entirely.
Both of these would have been missed by standard npm audit—one because it lacks a CVE, and one because it requires deep transitive scanning to detect. This is why we built the scanner.
Scan Your Dependencies
The tool is free and open source. The web UI is designed to be self-hosted on your own infrastructure for full control and privacy. Clone the repository and self-host it yourself.
Credits
Kris from Araptus built the original scanner, maintains the threat database, and contributed the multi-project scanner. His blog post covers the 2025 npm supply chain crisis in detail—including the Shai-Hulud worm, cryptocurrency hijacking attacks, and the 150,000-package token farming scam.
I contributed the deep scanning engine, web UI visualization enhancements—animated scan progress, campaign timeline, copy-to-clipboard commands—and the server integration. After I discovered the malware and documented additional findings, Kris merged the pull request. It's been a good collaboration.
Subscribe to Security Insights
Get enterprise security tips, compliance guides, and best practices delivered to your inbox.