On August 21, 2026, Trend Micro’s TrendAI research team disclosed 14 trojanized npm packages built around fake “streak tracker” and calendar-math utilities — names like streak-metrics-math, streak-map-cache, streak-calc-math, and map-streak-kit. None of them do anything useful. Their real job is to drop RedC2 4.0, a cross-platform post-exploitation implant that ships with an LLM-backed command layer the developers call Red Agent, letting an operator type a natural-language instruction and have it translated into beacon commands against a compromised fleet.

The interesting part for detection engineers isn’t the AI framing — it’s the delivery mechanism. This campaign skips the postinstall hook that most npm supply-chain detections are tuned for.

The Import-Time Execution Trick

Every prior npm supply-chain writeup on this site, including our AsyncAPI/Miasma coverage, focused on malicious postinstall scripts in package.json. RedC2’s loader doesn’t use one. Instead, the payload fires the moment dist/index.mjs is imported anywhere in the dependency graph — including a transitive dependency three levels deep that a developer never explicitly installed. The module re-exports legitimate-looking date/calendar utility functions (so npm test or a quick manual check looks clean) while, as a side effect of being loaded, it locates a bundled binary, chmods it executable, and launches it as a detached background process.

The binary itself rotates names across the 14 packages — math-core.bin, math-calc.bin, calc-math.dat, calc-cache.bin, calc.bin, calc-mapping.bin — and lives in dist/ or dist/internal/. Because there’s no postinstall script entry, npm install --ignore-scripts (our standard recommendation for supply-chain hardening) does not stop this campaign. The execution trigger is require/import, not the install lifecycle.

Once running, the Linux beacon (RedShell) performs a check-in registration with its C2 server, then enters a command loop that shells out through /bin/sh. Confirmed post-exploitation capabilities include interactive shell access, SSH key and browser credential harvesting, in-memory ELF execution, SOCKS5 proxying for network pivoting, and host/network enumeration. RedC2 targets Linux primarily but has Windows and macOS builds in the wild.

Detection 1: Executable Bit Set on a Binary Inside node_modules

The single highest-value signal is the chmod itself — legitimate npm packages essentially never mark a freshly unpacked file executable at runtime from inside node_modules.

title: Executable Permission Set on Binary Inside node_modules
id: 6a1e4c9d-2b7f-4e3a-9c5d-8f1b3e6a7c2d
status: experimental
description: |
  Detects chmod (or equivalent syscall) marking a file executable
  within a node_modules directory tree. RedC2 4.0's npm loader
  performs this at import time, not install time, so postinstall
  script blocking does not prevent it.
references:
  - https://thehackernews.com/2026/08/14-trojanized-npm-packages-drop-redc2.html
author: SOC Analyst Hub
date: 2026-08-22
tags:
  - attack.t1195.002
  - attack.t1222.002
logsource:
  category: file_event
  product: linux
detection:
  selection:
    ParentImage|endswith:
      - '/node'
    TargetFilename|contains: 'node_modules'
    TargetFilename|endswith:
      - '.bin'
      - '.dat'
  condition: selection
falsepositives:
  - Legitimate packages that ship precompiled native binaries with expected exec bits (verify path and hash)
level: high

KQL equivalent (Microsoft Defender for Endpoint / Sentinel):

DeviceFileEvents
| where InitiatingProcessFileName in~ ("node", "node.exe")
| where FolderPath has "node_modules"
| where FileName endswith ".bin" or FileName endswith ".dat"
| where ActionType in ("FileCreated", "FileRenamed") or PreviousFileName != ""
| project Timestamp, DeviceName, InitiatingProcessCommandLine, FolderPath, FileName

Detection 2: node Process Spawning a Detached Child Outside npm/node_modules Lifecycle

RedC2’s loader launches the extracted binary as a detached background process directly from the Node.js runtime, rather than through npm, yarn, or a build tool.

title: Node.js Process Spawning Non-JS Binary as Detached Child
id: 3f8d2a71-9c4e-4b1f-a6d3-e2c9f7b1a4d8
status: experimental
description: |
  Detects a node/node.exe process spawning a child process from a
  path inside node_modules that is not itself a node/npm/yarn
  binary. Matches the RedC2 4.0 import-time execution pattern.
references:
  - https://thehackernews.com/2026/08/14-trojanized-npm-packages-drop-redc2.html
author: SOC Analyst Hub
date: 2026-08-22
tags:
  - attack.t1195.002
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection:
    ParentImage|endswith: '/node'
    Image|contains: 'node_modules'
  filter_expected:
    Image|endswith:
      - '/npm'
      - '/npx'
      - '/node'
  condition: selection and not filter_expected
falsepositives:
  - Build tooling or test runners that legitimately spawn compiled helpers from node_modules
level: high

Detection 3: Beacon-Style Check-In Followed by SOCKS5 Proxy Traffic

RedShell’s check-in and command-loop pattern combined with SOCKS5 pivoting produces a recognizable network sequence: an outbound TCP connection from a node-spawned process, followed shortly by proxy-style traffic on non-standard ports from the same host.

let beacon_hosts =
    DeviceNetworkEvents
    | where InitiatingProcessParentFileName in~ ("node", "node.exe")
    | where RemotePort in (443, 8443, 4444, 8080)
    | where isnotempty(RemoteIP)
    | summarize FirstSeen = min(Timestamp) by DeviceId, RemoteIP, RemotePort;
DeviceNetworkEvents
| where RemotePort !in (80, 443, 22, 53)
| join kind=inner beacon_hosts on DeviceId
| where Timestamp between (FirstSeen .. FirstSeen + 15m)
| summarize DistinctRemoteIPs = dcount(RemoteIP), Ports = make_set(RemotePort) by DeviceId, bin(Timestamp, 15m)
| where DistinctRemoteIPs >= 3

Detection 4: SSH Key and Browser Credential File Access by a Node-Spawned Process

title: SSH Key or Browser Credential Store Accessed by Node-Spawned Process
id: 9b2e7d54-1a3f-4c8e-b7d1-a5f9c3e2b6d7
status: experimental
description: |
  Detects file reads of SSH private keys or browser credential
  databases by a process whose parent is node.js, matching RedC2's
  credential-harvesting capability.
references:
  - https://thehackernews.com/2026/08/14-trojanized-npm-packages-drop-redc2.html
author: SOC Analyst Hub
date: 2026-08-22
tags:
  - attack.t1552.004
  - attack.t1555.003
logsource:
  category: file_event
  product: linux
detection:
  selection:
    ParentImage|endswith: '/node'
    TargetFilename|contains:
      - '.ssh/id_'
      - 'Login Data'
      - '.mozilla/firefox'
      - 'Local State'
  condition: selection
falsepositives:
  - IDE or dev-tooling extensions that legitimately read SSH config for git operations
level: high

Hardening Beyond Signature Detection

npm install --ignore-scripts will not stop this campaign, which is the main reason it’s worth writing up separately from prior postinstall-focused coverage. Effective mitigations here are: pin and hash-verify lockfiles so a transitive dependency swap is visible in diff review; run install and build steps in ephemeral, network-egress-restricted containers so a beacon can’t reach its C2 even if it executes; and treat any unexplained executable-bit file appearing inside node_modules post-install as a high-confidence indicator, since no legitimate JS package needs to grant itself exec permissions at import time. Package names alone are a weak signal — this campaign will rename itself for the next wave — but the chmod-and-detached-spawn behavior is structural to how the loader works and is far more durable to detect on.