A Djinn in the Machine: TaskWeaver’s Node.js Intrusion Chain

Key Takeaways 

  • The Adversary Pursuit Group identified two previously undiscovered malware samples, TaskWeaver and Djinn Stealer. 
  • The intrusion began with confirmed exploitation of CVE-2026-48558, allowing the attacker to bypass SimpleHelp OIDC authentication and obtain a technician session. 
  • TaskWeaver is a heavily obfuscated Node.js loader, delivered as jquery.js and executed through node.exe, that implements an encrypted, reusable payload delivery channel rather than a fixed set of post exploitation commands. 
  • The observed second stage payload, Djinn Stealer, targets Windows, macOS, and Linux systems. 
  • Djinn Stealer collects credentials associated with cloud platforms, source control, package registries, infrastructure tooling, AI development assistants, browsers, SSH, and cryptocurrency wallets. 
  • Stolen AI assistant tokens can hand attackers everything the AI was trusted to access, including repositories, databases, and cloud accounts, extending the breach well beyond the AI itself. 
  • A single authentication bypass became a pathway into everything the managed systems could reach, from cloud platforms and code repositories to AI tools, cryptocurrency wallets, and customer infrastructure. 
  • The attacker repurposed legitimate RMM capabilities to transfer files and remotely execute malware across managed systems. 
  • Response actions must extend beyond isolating infected endpoints. Any credentials accessible from the system should be treated as potentially exposed. 

Executive Summary 

Blackpoint’s Adversary Pursuit Group (APG) investigated and contained an intrusion that began with the exploitation of CVE-2026-48558, a critical authentication bypass vulnerability affecting the OpenID Connect authentication flow in SimpleHelp Remote Monitoring and Management (RMM) software. By exploiting this vulnerability, the threat actor obtained an authenticated technician session on an internet-facing SimpleHelp server without possessing valid credentials. Using this access, the threat actor deployed two previously undocumented malware samples, which the APG has named TaskWeaver and Djinn Stealer

The compromised RMM platform provided the operator with a trusted administrative channel capable of transferring files and executing commands on systems managed through the server. The actor leveraged this access to mass deploy a heavily obfuscated JavaScript file named jquery.js, retrieved from a temporary Cloudflare hosted URL and executed through node.exe

Despite its filename, jquery.js was not related to the legitimate jQuery library. TaskWeaver was a modular Node.js loader designed to fingerprint the compromised system, establish encrypted communications with attacker-controlled infrastructure, and retrieve and execute additional JavaScript payloads with full access to the Node.js runtime. 

Static deobfuscation and controlled protocol analysis let the APG reconstruct TaskWeaver’s Command and Control (C2) protocol and recover the second-stage payload it delivered: a cross-platform information stealer named Djinn Stealer. Djinn is built to strip a developer’s machine of everything valuable in a single pass: the keys to cloud and infrastructure (cloud credentials, SSH keys, infrastructure secrets), the access that controls software itself (source control tokens and package registry authentication, a potential path to supply chain compromise), cryptocurrency wallets, and the browser data, saved sessions, and shell history flowing through the system. Most notably, it takes the credentials for AI development tools, giving an attacker a foothold to tamper with the very pipelines teams are building on. 

The breadth of the targeted data expanded the compromise beyond the RMM environment, creating potential exposure across cloud services, identity systems, software supply chains, AI development tooling and multiple customer tenants. Increasingly, developers grant AI assistants standing access to repositories, databases, and cloud accounts; the tokens behind those connections are stored on the workstation, so an attacker who steals them inherits the same downstream reach the developer extended to the AI, well beyond the AI service itself. Credentials accessible from a developer or administrator workstation may provide entry into production infrastructure, build pipelines, source code repositories, deployment platforms, cloud tenants, and customer environments long after the original endpoint has been contained. 

The use of compromised RMM infrastructure further amplified the risk. Activity launched through a trusted management product can resemble legitimate support operations, allowing malicious file transfers and command execution to blend into normal administrative workflows. For managed service providers, a single vulnerable management server may expose not only the provider’s internal environment but also the downstream systems entrusted to it by customers. 

Technical Analysis 

Identity Crisis 

CVE-2026-48558 affects the OIDC authentication process used by vulnerable SimpleHelp deployments. In affected configurations, the server accepts an identity token without properly verifying its cryptographic signature. An unauthenticated attacker can therefore construct a token containing arbitrary identity claims and use it to establish an authenticated technician session (Figure 1). 

Figure 1: A log entry showing the malicious authentication through the OIDC bypass. 

In this intrusion, exploitation of the vulnerability gave the threat actor access to SimpleHelp’s legitimate remote management capabilities. Rather than deploying malware through a conventional phishing attachment or standalone exploit, the operator used the RMM platform to retrieve and launch the next stage of the intrusion (Figure 2). This provided a trusted execution path and allowed activity to inherit the appearance of an authorized support session. 

Figure 2: Node.js runtime being dropped, then used to download and run TaskWeaver. 

The actor downloaded a JavaScript file named jquery.js from a randomly generated trycloudflare.com address and executed it through Node.js: node.exe <path>\jquery.js (Figure 3). 

Figure 3: Decoding the staging URL that jquery.js is retrieved from. 

The filename was selected to resemble the legitimate jQuery library, but the file was a 1.08 MB, single line, heavily obfuscated Node.js payload. The APG is tracking this loader as TaskWeaver

Loose Threads 

TaskWeaver was packaged as a webpack bundle but built to run outside a browser. Early in execution it reconstructs access to Node.js’s native require function at runtime, allowing it to load the modules it needs for operating system data, cryptography, file and path access, module loading, and process execution. Reconstructing require this way avoids the static calls, such as require(“crypto”) or require(“child_process”), that static analysis and security tooling typically key on (Figure 4). 

Figure 4: TaskWeaver rebuilding require at runtime to hide module loads 

In Node.js, require is the entry point to a program’s most powerful capabilities: reading files, spawning processes, performing cryptography, and making network connections. Detection logic frequently identifies malicious scripts by those literal require calls. Building require from generated code keeps them out of the file, so static inspection reveals almost nothing about the loader’s actual capabilities. 

The loader also checked for Electron runtime components. This made it capable of operating under a standard Node.js installation or within applications that embed a Node compatible JavaScript runtime. 

Once initialized, TaskWeaver collected a host fingerprint containing the operating system, hostname, MAC address, process information, process count, and Electron version when present (Figure 5). The fingerprint allowed the operator to identify the victim environment and potentially tailor payload delivery according to the system’s role or operating system. 

Figure 5: TaskWeaver builds a host fingerprint before it beacons. 

TaskWeaver protected its beacon with a hybrid encryption scheme. It generated a random 256-bit AES key, encrypted the collected system information with AES-256-GCM, and wrapped that AES key with an embedded RSA-2048 public key using RSA-OAEP (Figure 6). 

Figure 6: The beacon is encrypted with AES-256-GCM, and the key is wrapped with the embedded RSA key. 

Hybrid encryption pairs the strengths of two approaches. Symmetric encryption (AES) is fast but requires both sides to share one key. Asymmetric encryption (RSA) removes that requirement but is slow and size limited. Encrypting the data with a single-use AES key and then encrypting only that key with the operator’s RSA public key means only one party, the holder of the matching private key, can unwrap the key and read the data. Captured beacon traffic is therefore unreadable without the operator’s private key. 

The encrypted material was divided between the URL path and the request body before being sent (Figure 7). 

Figure 7: The beacon goes to a lookalike of Microsoft’s Dev Tunnels, split across the URL path and body of the request. 

The domain was designed to resemble Microsoft’s legitimate Dev Tunnels infrastructure, which uses the devtunnels.ms namespace. The attacker-controlled domain inserted a hyphen and used a different top level domain. 

TaskWeaver sent the beacon as an HTTPS POST request with a text/plain body. The C2 server returned a JSON object containing an action, a filename, and an encoded JavaScript payload: 


  “action”: “deliver”, 
  “script_name”: “upload”, 
  “payload_b64”: “<encoded payload>” 

 

The only command identified in TaskWeaver was deliver (Figure 8). This did not meaningfully restrict the loader because the delivered JavaScript executed with full Node.js functionality. 

Figure 8: The loader supports a single task, deliver, which executes a payload. 

After receiving a task, TaskWeaver recovered the payload using the embedded RSA public key, sanitized the requested filename, wrote the JavaScript to disk, and executed it inside a new runtime context. The delivered code received access to require, process, Buffer, timers, and other native Node.js capabilities. 

This design kept TaskWeaver minimal while preserving the ability to run arbitrary code. It needed no dedicated commands for shell access, screenshots, credential theft, or file transfer, since any of those could arrive as a new module on a later poll. 

A single-command loader is more capable than it appears; TaskWeaver is the delivery mechanism, not the payload. Because delivered JavaScript runs with full Node.js access, the deliver command is effectively “execute anything”. The same loader can push a credential stealer in one cycle and a backdoor, ransomware, or an internal scanner in the next, with no change to TaskWeaver itself.  

TaskWeaver’s obfuscation combined a custom basE91 implementation, scope-specific decoding alphabets, indirect constant tables, and flattened control flow. A single 8,410-character master blob was duplicated throughout the loader, and dozens of separate 91-character alphabets recovered different strings from it. Decoder calls sat inside dynamically calculated switch statements, and function names were reused across scopes with different decoding contexts, which defeats ordinary string extraction and obscures the control flow (Figure 9). 

Figure 9: TaskWeaver is delivered as one obfuscated 1.08MB line of JavaScript. 

Functionally, it is one encoded block read through dozens of different alphabets, where each alphabet is only valid in one region of the program. Every string the loader depends on, including its module names, C2 domain, and task format, lives in that block, but no single alphabet decodes all of it, which is why text extraction tools return nothing useful. The weakness is that each encoded offset can be tested against every alphabet, and in most cases only the correct one yields readable output. Applying that across the loader recovered its full string set, including imports, C2 domain, beacon structure, cryptographic routines, and task format, without executing the sample (Figure 10). 

Figure 10: The same strings become readable after deobfuscation. 

Reconstructing the protocol made it possible to build a client that reproduced TaskWeaver’s beacon and response handling logic. The client was first validated against a local mock C2 server, confirming the AES encryption, RSA wrapping, request format, and response recovery logic matched the behavior extracted from the loader. It was then used to issue a request to the live C2 server and retrieve a deliver task containing a script named upload. Its response consisted of 1,171 RSA framed blocks that recovered into a 298,474 byte JavaScript file. 

Your Wish Is My Command 

The recovered payload, Djinn Stealer, reuses TaskWeaver’s obfuscation framework and embeds the identical RSA public key, firmly linking the two together.  

Djinn Stealer implemented a rules-based collection engine for Windows, macOS, and Linux. It enumerated candidate user home directories, expanded hard coded file and directory rules, recursively traversed selected locations, removed duplicate results, and excluded common sources of noise such as caches, logs, temporary files, .git directories, node_modules, and __pycache__ (Figure 11). 

Figure 11: Djinn Stealer walks a hardcoded rule set and skips noisier directories. 

The stealer also enforced limits on individual file sizes, collection depth, files collected per rule, and total files collected. These controls likely reduced execution time, constrained archive size, and lowered the risk of creating conspicuous outbound transfers. 

In addition to copying existing files, Djinn Stealer generated several reconnaissance artifacts: 

  • processList.txt 
  • linux-process-env.json 
  • env.json 
  • telemetry.json 
  • user-dirs.txt 

On Linux systems, the malware attempted to read /proc/<pid>/cmdline and /proc/<pid>/environ (Figure 12). These files may expose passwords, API keys, access tokens, database connection strings, and other sensitive values passed through command line arguments or environment variables. 

Figure 12: The stealer targets each process’ environment variables from /proc. 

Djinn Stealer’s collection rules extended far beyond conventional browser credential theft. It searched for configuration and authentication data associated with AWS, Azure, Google Cloud, Oracle Cloud Infrastructure, Okta, Cloudflare, DigitalOcean, Linode, Heroku, Vercel, Railway, Supabase, Pulumi, Terraform, HashiCorp Vault, Consul, and numerous additional cloud services (Figure 13). 

Figure 13: Collection rules targeting cloud, developer, and package registry credentials. 

Developer and deployment targets included GitHub CLI data, Git configuration, SSH keys, Docker authentication, Helm registry information, S3 and MinIO client configurations, and Subversion credentials. 

The stealer also targeted package registry and build-tool credentials for npm, pnpm, Yarn, NuGet, Cargo, Composer, Maven, Gradle, pip, PyPI, Conda, Bun, Ivy, and Scala Build Tool. Theft of these credentials could enable an attacker to access private packages, alter dependencies, or publish malicious software under a trusted organization or developer identity. 

Djinn Stealer carried an unusually broad set of collection rules for AI assisted development tools, targeting the configuration, authentication, session, and project data associated with Claude, Gemini, Codex, Cline, OpenCode, and Kilo (Figure 14). 

Figure 14: Djinn Stealer collection rules for AI development tools. 

Many of these tools rely on the Model Context Protocol (MCP) to connect an AI assistant to external tools and data on the developer’s behalf, including source repositories, databases, cloud accounts, and internal APIs. The settings and tokens for those connections are stored locally in files such as ~/.claude/mcp.json. Stealing them can grant an attacker the same downstream access the developer extended to their AI agent, reaching well beyond the AI service itself.  

The malware also searched for cryptocurrency wallets and keystores associated with Bitcoin, Litecoin, Dogecoin, Dash, Ethereum, Monero, Zcash, Exodus, Atomic Wallet, and Electrum (Figure 15). Browser history, bookmarks, shell history, database client files, PGP data, SSH configuration, and operating system information were also included in its collection scope. Stolen wallet credentials enable direct financial theft, while harvested SSH configurations and system data can provide threat actors with persistent footholds across additional infrastructure.  

Figure 15: Cryptocurrency wallet and keystore paths in the collection rules. 

After gathering the targeted files, Djinn Stealer created a PAX format tar archive and compressed it with gzip. It encrypted the archive using AES-256-GCM and wrapped the randomly generated AES key with the same RSA-2048 public key embedded in TaskWeaver (Figure 16). 

Figure 16: Collected files are archived, encrypted, and sent in a single POST. 
 

Although the exfiltration channel used plain HTTP, the archive was encrypted before leaving the host. Network inspection can identify the connection and its metadata but cannot recover the contents without the operator’s RSA private key. 

C2 responses are signed with the operator’s private key and verified with the public key embedded in the loader, which is what allowed the second stage to be recovered from the sample alone. Exfiltration runs the opposite direction: collected data is encrypted to that same public key, so only the operator’s private key can decrypt it. The upload is observable, but its contents are not recoverable from captured traffic. 

The final architecture separated each operational function. CVE-2026-48558 provided entry into the trusted RMM platform. SimpleHelp provided remote execution and file transfer. TaskWeaver established an encrypted and reusable payload delivery mechanism. Djinn Stealer collected and exfiltrated credentials capable of unlocking cloud, development, financial, and customer environments. 

Indicators of Compromise (IoCs) 

File Indicators 

Indicator FileName SHA-256 
TaskWeaver jquery.js 00cc86d1144020c24c8fbb3a8dc6b908926497ebd23be3bf854360f93d1c8f4c 
Djinn Stealer upload f4a72600a3735c2a4d843875ea61bbb6f935a1af51a81f2fbc992ce11ba94afc 

The Djinn Stealer hashes apply to the decoded payload recovered during analysis. The payload was transferred over the network as RSA-framed data contained in the payload_b64 response field. 

Network Indicators 

Type Indicator 
Loader staging *.trycloudflare[.]com 
TaskWeaver C2 a[.]dev-tunnels[.]com 
TaskWeaver URI pattern POST /api/<base64url>.<base64url>.<base64url> 
Djinn Stealer exfiltration 96[.]126[.]130[.]126:58942 
Djinn Stealer User-Agent telemetry-client/1.0 

Host and Behavioral Indicators 

Type Indicator 
Execution node.exe <path>\jquery.js 
TaskWeaver filename jquery.js 
Djinn Stealer filename upload 
Reconnaissance output processList.txt 
Reconnaissance output linux-process-env.json 
Reconnaissance output env.json 
Reconnaissance output telemetry.json 
Reconnaissance output user-dirs.txt 

Recommendations for MSPs 

  • Patch and restrict SimpleHelp immediately. Confirm the deployed version and OIDC configuration, upgrade beyond affected releases, and remove vulnerable systems from direct internet exposure until remediation is complete. 
  • Investigate for prior exploitation. Review authentication, technician, configuration, session, file-transfer, and command-execution logs for unauthorized access, newly created accounts, OIDC changes, unfamiliar IP addresses, anomalous login times, or activity without a corresponding support ticket. 
  • Invalidate active sessions and rotate exposed secrets. Terminate technician sessions and rotate credentials, API keys, integration secrets, and identity-provider configuration associated with the SimpleHelp server. 
  • Treat RMM platforms as privileged infrastructure. Place administrative interfaces behind a VPN or identity-aware proxy and enforce phishing-resistant MFA, source restrictions, dedicated administrative workstations, and least-privilege access. 
  • Segment technician access. Restrict permissions by customer, device group, support function, and administrative purpose to prevent one compromised account or server from exposing every downstream environment. 
  • Detect suspicious runtime execution. Alert when RMM software launches Node.js, PowerShell, Python, Deno, or Bun, particularly from temporary, download, remote-support, or user-writable directories. 
  • Apply application control. Block unnecessary scripting runtimes. Where Node.js is required, restrict execution to approved directories and validated scripts. 
  • Restrict temporary tunneling services. Block services such as trycloudflare[.]com when not required. Where permitted, monitor downloads of scripts, archives, and executable content. 
  • Reduce reliance on long-lived credentials. Use short-lived, workload-bound identities and remove unnecessary production secrets from developer endpoints. 

Conclusion 

This intrusion demonstrates how quickly a vulnerability in trusted management infrastructure can move beyond the affected server. 

Exploitation of CVE-2026-48558 did not merely provide access to a SimpleHelp console. It gave the attacker a legitimate administrative pathway into managed systems. From that position, the operator deployed TaskWeaver, established a separate encrypted payload channel, and delivered Djinn Stealer to collect credentials capable of reaching cloud platforms, code repositories, software pipelines, package registries, AI development tools, cryptocurrency wallets, and customer infrastructure. 

The most damaging outcome may therefore occur after the original endpoint has been isolated. A stolen cloud key, package publishing token, source-control session, SSH key, or AI integration credential can preserve access independently of the compromised RMM server. These credentials can allow an attacker to re-enter the environment through trusted services, alter software, access production data, or pivot into customer tenants without redeploying the original malware. 

For MSPs, this creates a concentration of risk problem. RMM platforms exist to centralize access and simplify administration. Those same characteristics make them valuable targets. A vulnerability affecting one externally exposed management server can provide an attacker with reach across multiple customers and make malicious activity appear to originate from a trusted provider. 

Stopping this type of intrusion requires more than rapid patch deployment. MSPs must reduce the exposure of management interfaces, enforce strong and segmented technician access, scrutinize RMM driven execution, control script runtimes, limit long lived developer credentials, and maintain visibility into the cloud and software systems those credentials can unlock. 

TaskWeaver and Djinn Stealer illustrate a modern intrusion model in which the endpoint is only the first step. The true objective is the collection of portable identities and secrets that connect developers and administrators to the broader enterprise. Effective containment must follow those credentials wherever they lead. 

DATE PUBLISHEDJune 29, 2026
AUTHORNevan Beal and Sam Decker

2026 Annual Threat Report

What actually worked for attackers in 2025.

Most attackers aren’t breaking in
They’re logging in

Explore the real patterns behind modern intrusions in the 2026 Annual Threat Report

GET THE REPORT