CVE
Not assigned
CWE
CWE-506
Affected Surface
- 14 trojanized npm date and streak packages led by streak-metrics-math@1.0.0 and 1.0.1
- Linux developer workstations that installed and imported any of the affected packages
- Linux CI runners, build containers, and Node.js workloads with transitive imports of the affected packages
- Hosts that rely on npm `--ignore-scripts` as their main install-time malware control
TrendAI published one of the more important package-malware disclosures of August on 21 August 2026: fourteen npm packages that look like tiny date and streak helpers but launch a Linux implant as soon as the module is imported. This is not another preinstall or postinstall story. The malicious path sits in the runtime entrypoint, so the package can survive a quick install smoke test and still execute on the first real import.
That distinction matters for application security teams because these packages were built to look ordinary in the exact places many teams trust most: no heavy dependency tree, working exported helpers, and no obvious lifecycle hook. If one of these names lands anywhere in a dependency graph, especially as a transitive dependency on a Linux host, a normal import is enough to start the payload.
Affected packages
TrendAI’s package list is small enough to enumerate in full:
streak-metrics-math@1.0.0streak-metrics-math@1.0.1kit-map-vim@1.0.0streak-map-cache@1.0.0streak-map-kit@1.0.0map-streak-kit@1.0.0streak-cache-map@1.0.0streak-calc-metrics@1.0.0streak-calc-math@1.0.0streak-math-abz@1.0.0streak-metricsaz@1.0.0streak-math-metrics@1.0.0streak-metricazbd@1.0.0streak-metricsazb@1.0.0streak-kit-map@1.0.0
The packages present themselves as no-frills day math utilities. TrendAI reports that the expected helper logic lives in dist/internal/daymath.mjs, with functions that really do group dates, calculate deltas, and identify streak targets. That is precisely why a superficial “does it work?” review would miss the problem.
The execution path: harmless exports plus a hidden loader
The malicious path is the package entry file, dist/index.mjs.
TrendAI describes index.mjs as a trojanized loader that does two things in the same file:
re-export day math helpers
-> resolve bundled ELF beside import.meta.url
-> chmod the file to 0755
-> compare the file's SHA-256 against a hardcoded value
-> spawn the ELF as a detached process
The important point is where this logic lives. It is not behind a function call the application has to make later. TrendAI says it runs inside an async IIFE that evaluates when the module loads. That means the dangerous event is not “someone called the suspicious API.” The dangerous event is “a Node process imported the package.”
TrendAI’s write-up calls out the concrete behaviors:
- the loader resolves the binary relative to
import.meta.url - it sets executable permissions with
fs.chmodSync(binaryPath, 0o755) - it validates the dropped file against a hardcoded SHA-256 digest
- it starts the payload with
cp.spawn(...) - it uses
shell: falseanddetached: true
That last pair is worth pausing on. shell: false avoids the extra shell parent that defenders often key on in process-lineage rules, while detached: true lets the implant survive after the importing Node process exits.
Why --ignore-scripts is not enough
Many teams now treat “npm install --ignore-scripts passed” as a strong first-pass defense against registry malware. This campaign is a clean example of why that control is necessary but not sufficient.
The loader does not rely on preinstall, install, or postinstall. TrendAI explicitly states that no install hook is needed and that a single import anywhere in the dependency graph, including a transitive one, is enough to execute the payload. In practice, that means:
- a developer can install the package without seeing a noisy lifecycle hook
- a CI job can pass the install phase and fail only after test or build code imports the module
- a transitive dependency can trip the loader even when the application does not reference the package name directly
This is the same trust-boundary problem defenders have been seeing elsewhere in 2026. The initial compromise is no longer confined to the package-manager event. It can be deferred into the runtime event.
What gets launched
TrendAI links the bundled ELF to RedShell, the Linux implant for the RedC2 4.0 command-and-control framework. Their report goes well beyond “it beacons out.” It describes a mature Linux payload with:
- interactive shell execution
- file transfer and bulk collection
- SSH key and browser credential theft
- local database discovery
memfd-based ELF execution- executable memory mapping for shellcode execution
- persistence via
cron,~/.bashrc, usersystemd, and XDG autostart - SOCKS5 proxying and TCP port forwarding
TrendAI also reports that the C2 side includes “Red Agent,” a natural-language control layer that translates prompts into ordered beacon commands. That detail does not make the initial npm compromise more exploitable, but it does raise the operational risk after compromise because the payload is designed for a lower-friction post-exploitation workflow.
The file layout that matters
TrendAI reports that each package stores the ELF under either dist/ or dist/internal/, disguised as a native math accelerator. The filenames vary:
math-core.binmath-calc.bincalc-math.datcalc-cache.bincalc.bincalc-mapping.bin
That layout matters for triage because the package keeps the legitimate utility story intact. The JavaScript code still exports date helpers, while the binary sits in a place that could be dismissed as a compiled performance helper if a reviewer only spends a minute on the tarball.
Detection and hunting
Start with dependency inventory, not code search alone.
rg -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)"' \
package.json package-lock.json pnpm-lock.yaml yarn.lock
Then hunt for the loader and dropped-binary markers inside caches, extracted dependencies, and build workspaces:
rg -n 'daymath\.mjs|import\.meta\.url|chmodSync\(binaryPath, 0o755\)|detached:\s*true|math-core\.bin|math-calc\.bin|calc-math\.dat|calc-cache\.bin|calc\.bin|calc-mapping\.bin' \
node_modules .npm _cacache
On Linux endpoints and runners, review process telemetry for detached child execution from Node.js around build or test time. The loader design means the suspicious process may outlive the parent import path that started it.
Network hunting should focus on post-import outbound traffic from build workers and developer laptops, not only on the install phase.
Response guidance
If any of these packages were present on a Linux host and you cannot rule out import-time execution, treat the machine as compromised.
Recommended response:
- Remove the affected package and purge dependency caches.
- Rebuild the environment from a known-clean base image where possible.
- Rotate credentials exposed to the host, including source-control tokens, registry tokens, SSH keys, cloud credentials, kubeconfigs, and browser-stored secrets.
- Review user
systemdunits,cron, shell profiles, and XDG autostart paths for persistence. - Inspect build logs and runtime traces for the first import event, not just the install event.
The harder lesson is architectural. This campaign did not need npm lifecycle hooks because the attacker moved execution to the place developers and frameworks already trust: module import. Teams that only gate on install scripts or package manifests will miss this class of package compromise.
From research to remediation
Check whether this pattern exists in your codebase
Turn this research into a remediation workflow. Scan dependencies and package manifests for similar supply-chain risk, then prioritize fixes with reachability context.