The npm ecosystem underpins millions of JavaScript and TypeScript projects worldwide, providing reusable modules via the Node Package Manager. Unfortunately, that popularity also makes npm a high-value target for software supply-chain attacks. A recent discovery by Veracode’s Threat Research team reveals an exceptionally stealthy malware campaign embedded within a seemingly innocuous npm package called buildrunner-dev—one that hides a sophisticated .NET Remote Access Trojan (RAT) inside PNG images using steganography.
The Package and Initial Discovery
At first glance, buildrunner-dev appears trivial: a package.json file and a post-install hook. However, the post-install hook runs a script (init.js) during installation, which retrieves additional components at install time from a remote repository. This approach means the malicious code isn’t directly in the npm package itself, helping it evade basic static scanning.
The package name is a typosquat of legitimate packages like buildrunner or build-runner, meaning developers searching for related build tooling might accidentally select it, presuming it a maintained fork. Typosquatting—the practice of publishing misleadingly named packages—is a common supply-chain risk.
Installation: The Dropper Script
When a developer runs npm install buildrunner-dev, the init.js script executes automatically. This script:
- Downloads a batch file (
packageloader.bat) from an external hosting source. - Saves it to the Windows Startup folder to achieve persistence on reboot.
- Skips execution in continuous integration (CI) environments and on non-Windows platforms—an evasion tactic.
The batch file itself is heavily obfuscated, containing thousands of lines where only a handful actually matter. The obfuscation includes:
- Defined but unused variables
- Random English words as noise
- Encoded strings broken into fragments
This makes analysis by both humans and static tools difficult.
Steganographic Payload: Malware Hidden in Pixels
The key innovation in this attack is where the malware actually lives. Both the AMSI bypass code and the main RAT payload are hidden within two PNG images hosted on an image hosting service. These images look like noise to the naked eye but contain encoded binaries mapped to pixel RGB values:
- The first two pixels encode the size of the hidden payload.
- Subsequent pixels carry raw bytes in their R, G, and B channels.
By extracting pixels in order, the attacker can reconstruct executable code that would never be present as a typical .js or .exe file in the npm package. This steganographic technique enables payload delivery without storing traditional malware artifacts in the registry itself.
Payload Components
Two embedded payloads are extracted:
- AMSI Bypass Script
A PowerShell script that patches the Windows Anti-Malware Scan Interface (AMSI) to disable runtime scanning. - .NET RAT (Remote Access Trojan)
A reflective loader written in .NET is extracted and executed from memory. This RAT:- Uses process hollowing to inject itself into a legitimate Windows process
- Bypasses security controls
- Establishes persistence and connects to a command-and-control (C2) server
- Contains fallback logic to evade different AV products
Reflective loading and process hollowing are advanced post-exploitation techniques that let malicious code run under the guise of normal system processes, evading many detection tools.
Threat Implications
This attack illustrates how software supply chains can be weaponized without large malware binaries stored directly in repositories. By embedding malware in pixels and retrieving initial execution logic at install time, attackers avoid many traditional detection mechanisms. Such techniques emphasize the importance of:
- Supply chain visibility: Understanding all components and transitive dependencies in your codebase.
- Runtime security controls: Monitoring for unusual activity during dependency installation.
- Secure defaults and isolation: Running installs with minimal privileges and in controlled environments.
Across the broader npm ecosystem, similar attacks are increasing in frequency and sophistication. For example, recent widespread npm supply chain compromises inserted malware into packages to steal cryptocurrency or propagate self-replicating worms through compromised libraries.
Conclusion
Malicious packages like buildrunner-dev showcase how supply chain attacks can evolve beyond simple command execution or backdoors in JavaScript. By hiding sophisticated payloads inside seemingly innocuous artifacts (like images) and using evasion techniques, attackers raise the bar for defenders. Comprehensive dependency scanning, runtime behavioral analysis, and secure software development practices are essential to defending modern application supply chains.
