Fourteen npm packages just shipped a Linux backdoor that fires the moment the module is imported. No install script, no function call, no user action. If your supply-chain controls still treat "no postinstall hook" as a safety signal, this campaign is the argument for changing that.
The loader: working utilities, malicious import

TrendAI, Trend Micro's enterprise security business, disclosed the campaign in a report covered publicly on August 21, 2026. The 14 packages pose as calendar and streak utilities, and here is the part that makes them nasty: they work. The promised date math is actually in there, so nothing looks broken in a code review, a test run, or a quick skim of the source. The backdoor hides behind a feature the packages describe as a "native math accelerator."
Security researcher Aliakbar Zahravi describes the delivery this way: "Delivery is handled by the package entry file, dist/index.mjs, which acts as a trojan loader." When the module loads, it locates a bundled binary, marks it executable with chmod, and launches it as a detached background process. TrendAI's phrasing is the sentence every AppSec team should read twice: "No install hook function call is needed; a single import anywhere in the dependency graph, even a transitive one, is enough to execute the payload."
Think about what that defeats. Install-time sandboxing sees nothing because nothing happens at install time. Dependency review gates that flag lifecycle scripts wave it through. And the transitive angle means none of your developers had to choose these packages. Anything that depends on them, four levels deep, fires the implant the first time the module graph resolves, with your app's environment variables, file access, and network position.
RedShell: the Linux piece RedC2 was missing
RedC2 is a commercial command-and-control framework sold on cybercrime forums, and it has been iterating fast: version 2.0 in August 2025, 3.0 in January 2026, and 4.0 advertised in early June 2026 by a seller calling themselves MarlboroMan on Hack Forums, pitched as "built for evasion." It retails for $99.99 on a clearnet site branded Red Offsec, complete with a Terms of Service that prohibits unauthorized computer access. A hundred-dollar C2 with an honor system. That is the market defenders are up against.
Version 4.0's headline addition is RedShell, a Linux beacon, and it is what the npm campaign drops. RedShell gives the operator an interactive shell via /bin/sh plus Linux-specific commands for system discovery, file operations, data collection (SSH keys and browser credentials are called out explicitly), execution, persistence, in-memory ELF execution, SOCKS5 proxying, and network pivoting. On first run it gathers basic system information and sends a check-in message to the C2 server, then sits in a loop executing operator commands through /bin/sh and returning results.
The framework also ships Windows and macOS beacons (UAC bypass and AV tampering on the Windows side, recon and data harvesting on macOS). This campaign delivers the Linux one, and that targeting is not random. Linux is where CI runners, build agents, and server-side Node workloads live, and it is where a stolen SSH key buys the most.
Indicators you can grep for right now
The 14 packages, all published at 1.0.0 unless noted:
| Package | Version(s) |
|---|---|
| streak-metrics-math | 1.0.0, 1.0.1 |
| kit-map-vim | 1.0.0 |
| streak-map-cache | 1.0.0 |
| streak-map-kit | 1.0.0 |
| map-streak-kit | 1.0.0 |
| streak-cache-map | 1.0.0 |
| streak-calc-metrics | 1.0.0 |
| streak-calc-math | 1.0.0 |
| streak-math-abz | 1.0.0 |
| streak-metricsaz | 1.0.0 |
| streak-math-metrics | 1.0.0 |
| streak-metricazbd | 1.0.0 |
| streak-metricsazb | 1.0.0 |
| streak-kit-map | 1.0.0 |
Only streak-metrics-math shipped more than one version. Everything else appeared once, at 1.0.0, which suggests a spray-and-test operation rather than maintained malware.
The bundled implant uses one of six filenames: math-core.bin, math-calc.bin, calc-math.dat, calc-cache.bin, calc.bin, or calc-mapping.bin. It sits either directly in dist/ or one level down in dist/internal/. For file hashes, pull them from the TrendAI report itself rather than from summaries, mine included.
Detection engineering: where this thing actually shows up
Execution from inside node_modules
The single cleanest host signal. Almost nothing legitimate executes a binary straight out of node_modules on a server, and the exceptions are known native build helpers.
title: Binary Executed From node_modules Directory
logsource:
product: linux
category: process_creation
detection:
selection:
Image|contains: '/node_modules/'
filter_native_build_tools:
Image|contains:
- '/esbuild'
- '/@swc'
- '/sharp'
condition: selection and not filter_native_build_tools
level: highThe filter is a starting point. Baseline your build fleets before you turn this loose, because native compile helpers will otherwise drown you.
chmod against a bundled binary
title: Chmod Applied To File Inside node_modules
logsource:
product: linux
category: process_creation
detection:
selection:
Image|endswith: '/chmod'
CommandLine|contains: 'node_modules'
condition: selection
level: mediumOne honest limitation: a Node loader can chmod via the fs API instead of spawning the chmod binary, and then no process_creation event fires at all. Cover that gap with auditd or eBPF on the chmod syscall, or catch the loader statically before it ever runs, which brings us to YARA.
A starter YARA rule for the loader
Run this against your registry mirror, artifact cache, or in CI whenever the dependency tree changes. It keys on the implant filenames plus the behavioral strings a detached-spawn loader needs.
rule RedC2_NPM_Trojan_Loader
{
meta:
description = "Trojan-loader pattern in npm entry files (RedC2 4.0 campaign)"
strings:
$bin1 = "math-core.bin"
$bin2 = "math-calc.bin"
$bin3 = "calc-math.dat"
$bin4 = "calc-cache.bin"
$bin5 = "calc-mapping.bin"
$bin6 = "calc.bin"
$b1 = "child_process"
$b2 = "detached"
$b3 = "chmod"
$b4 = "unref"
condition:
filesize < 200KB and any of ($bin*) and 2 of ($b*)
}calc.bin is short and will false-positive on its own, which is why the rule demands the spawn-and-chmod behavior strings alongside it. Tune from there.
Process lineage on live hosts
The runtime chain is node spawning the implant, the implant spawning /bin/sh, all detached from the terminal. On a live Linux host, this one-liner finds processes whose executable resolves under node_modules:
ls -l /proc/[0-9]*/exe 2>/dev/null | grep node_modulesAnything that comes back on a production host or CI runner is worth your afternoon.
What the AI angle actually changes, and what it does not
Here is the skeptical take, and it deserves a fair hearing: the LLM never touches the wire. Red Agent, the component Red Offsec markets as an "AI-powered command execution system specialized for penetration testing," sits on the operator side alongside the RedC2 EXT command-line extension. Per TrendAI, it talks to "a model tuned for red-team operations" that translates natural-language prompts into command sequences, which the beacon then executes through /bin/sh like any other instructions. The beacon itself is dumb. The protocol between beacon and server does not become undetectable because a model phrased the commands.
All true, and it still misses the point. Two things genuinely change.
First, operator behavior. Human operators have habits: characteristic command ordering, pacing, typos, favorite one-liners. A quiet amount of C2 detection work leans on that consistency, whether people admit it or not. When a tuned model generates the sequence, recon flows into credential access flows into staging as a coherent chain, at machine pacing, regardless of who is driving the console. Detections tuned to human rhythm decay.
Second, operator population. RedC2 costs $99.99 and now accepts plain English. The skill floor for running a multi-stage Linux intrusion drops, which means the expected volume of competent-looking intrusions from unremarkable actors goes up. Cheap plus easy is how techniques spread, and TrendAI makes the same point about operators of varying skill levels running complex intrusions efficiently.
The defensive consequence is concrete. Spend less effort trying to recognize the operator and more on what stays constant no matter who, or what, is at the console: a binary executing out of node_modules, in-memory ELF execution, reads of ~/.ssh and browser credential stores, a build host holding open a SOCKS5-style egress session it has no business holding. The model can rewrite the playbook. It cannot make the beacon stop doing beacon things.
Same-day audit and remediation workflow
- Search every lockfile you own, across every repo and every built artifact:
printf '%s\n' streak-metrics-math kit-map-vim streak-map-cache \
streak-map-kit map-streak-kit streak-cache-map streak-calc-metrics \
streak-calc-math streak-math-abz streak-metricsaz streak-math-metrics \
streak-metricazbd streak-metricsazb streak-kit-map > /tmp/redc2.txt
rg -Ff /tmp/redc2.txt --glob 'package-lock.json' \
--glob 'yarn.lock' --glob 'pnpm-lock.yaml'- For any hit, trace the path in with
npm ls <package-name>to find which top-level dependency pulled it. If nothing shows, check CI base images, Docker layers, and vendored node_modules. Transitive inclusion is the likely story. - Treat any host that imported the package as compromised. Check live processes with the /proc one-liner above, look for persistence, and review egress for periodic check-in-style connections from hosts that should not be initiating outbound sessions at all.
- Rotate credentials on affected hosts. SSH keys and browser-stored credentials are documented collection targets, and assume environment variables and CI secrets on the box were readable too. Rotation is not optional here.
- Remove the package, pin replacements, and rebuild affected artifacts and images from clean bases. A beacon with persistence and in-memory execution in its feature list means "we uninstalled it" is not remediation.
- Block the 14 names at your registry proxy regardless of their current registry status, so mirrors and caches cannot quietly re-serve them.
- Ship the detections from this article now. The pattern, import-time loader plus chmod plus detached spawn, is cheap to copy and very public. The next campaign using it will not bother with streak-themed names.
Key takeaways
- The payload executes at import time. Audit runtime behavior and lockfiles, not install hooks.
- Grep today for 14 package names and six binary filenames under
dist/ordist/internal/. - Anchor detection on execution from node_modules, chmod on bundled files, and Node processes with detached children.
- The LLM sits operator-side. Expect more intrusions, better sequenced, from less-skilled actors, not a new wire protocol. Host telemetry remains the stable signal.
- An import is a compromise: rotate SSH keys, browser credentials, and CI secrets, then rebuild from clean bases.




