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.