registry  /  cursed-ecto-d3ab00  /  2.0.0

cursed-ecto-d3ab00@2.0.0

ecto module

AI Security Review

scanned 7d ago · by lpm-firewall-ai

The package executes an install-time exfiltration script during preinstall and postinstall. It harvests environment variables, likely flag/secret files, and command output, then sends the data to an external webhook.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install or any installer running preinstall/postinstall lifecycle scripts
Impact
Secrets, npm tokens, filesystem flag files, host/user metadata, and shell command output can be disclosed to the attacker.
Mechanism
install-time credential, file, and command-output exfiltration
Attack narrative
On installation, package lifecycle scripts run exfil.js for both preinstall and postinstall. The script gathers host/user/cwd metadata, filters environment variables for secret-like names, reads common flag file locations, executes local discovery commands, and transmits the JSON body to a webhook.site collector with a GET fallback carrying base64 data.
Rationale
Direct source inspection confirms concrete install-time exfiltration behavior with external network transmission and no package-aligned benign purpose. This should be blocked from publication/installation by the firewall.
Evidence
package.jsonexfil.jsindex.js/flag/flag.txt/flag/flag.txt/root/flag/root/flag.txt/app/flag/app/flag.txtflagflag.txt../flag.txt/home/node/flag.txt/opt/flag.txt/tmp/flag.txt
Network endpoints1
webhook.site/e2e3a401-da3d-4ecb-bc41-d3c4c4b7dddd

OSV Corroboration

OpenSSF/OSV
Advisory
MAL-2026-10061
Source
OpenSSF Malicious Packages via OSV
Summary
Malicious code in cursed-ecto-d3ab00 (npm)
Details
The package has no legitimate functionality (index.js is an empty module) and exists solely to run an install-time attack payload. All four lifecycle hooks (preinstall.js, install.js, postinstall.js, prepare.js) execute the same shell command via child_process.execSync that recursively scans host filesystem paths (/app, /opt, /root, /home, /srv, /data, /var, /etc, /tmp, /flag*, /) for HTB{...} flag patterns, enumerates flag-named files with their contents, captures env, hostname, id, and pwd, base64-encodes the collected data, and exfiltrates it via HTTPS GET to a hardcoded Cloudflare quick-tunnel endpoint at forward-amber-prairie-ruled.trycloudflare.com. In addition, each lifecycle script fans out HTTP PUT requests to internal hostnames and loopback ports (127.0.0.1:3000/8080/80/5000/4000 and hostnames app, web, frontend, console, ecto, registry, backend, nginx) targeting path /api/modules/ECT-839201 with a crafted ecto_module manifest named PWNED, attempting to register a malicious module on adjacent services reachable from the install environment. Behavior fires unconditionally on npm install.

Decision evidence

public snapshot
AI called this Malicious at 99.0% confidence as Malware with low false-positive risk.
Evidence for block
  • package.json defines preinstall and postinstall hooks: node exfil.js <phase>.
  • exfil.js collects matching env vars including secret/token/npm names into result.env_flag.
  • exfil.js reads likely flag paths including /flag, /root/flag.txt, local flag.txt, and ../flag.txt.
  • exfil.js runs child_process execSync discovery commands including id, hostname, find / '*flag*', cat /flag*, and env grep token.
  • exfil.js sends collected host, cwd, user, env, file, and command output to webhook.site via POST and fallback GET.
  • index.js is empty, so install-time exfiltration is the meaningful behavior.
Evidence against
  • No obfuscation or persistence found in inspected files.
  • No benign package functionality found that would justify credential/file/command-output collection.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetwork
Supply chain
UrlStrings
Manifest
NoLicense
scanned 2 file(s), 2.56 KB of source, external domains: webhook.site

Source & flagged code

8 flagged · loading source
package.jsonView file
scripts.preinstall = node exfil.js preinstall
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.preinstall = node exfil.js preinstall
Medium
Ambiguous Install Lifecycle Script

Install-time lifecycle script is not statically allowlisted and needs review.

package.jsonView on unpkg
scripts.postinstall = node exfil.js postinstall
Medium
Ambiguous Install Lifecycle Script

Install-time lifecycle script is not statically allowlisted and needs review.

package.jsonView on unpkg
exfil.jsView file
1// Exfiltration payload. Uses only Node built-ins so it runs on any Node engine. L2: const https = require("https"); L3: const http = require("http"); L4: const cp = require("child_process"); L5: const fs = require("fs"); ... L11: phase: process.argv[2] || "unknown", L12: host: safe(() => os.hostname()), L13: cwd: safe(() => process.cwd()), ... L24: // Grab any interesting env vars L25: for (const k of Object.keys(process.env)) { L26: if (/flag|secret|token|npm|ecto|corsair|ghost|spectral/i.test(k)) { ... L53: try { result.cmds[c] = cp.execSync(c, { timeout: 8000 }).toString(); }
Critical
Credential Exfiltration

Source appears to send environment or credential material to an external endpoint.

exfil.jsView on unpkg · L1
1// Exfiltration payload. Uses only Node built-ins so it runs on any Node engine. L2: const https = require("https"); L3: const http = require("http"); L4: const cp = require("child_process"); L5: const fs = require("fs"); ... L11: phase: process.argv[2] || "unknown", L12: host: safe(() => os.hostname()), L13: cwd: safe(() => process.cwd()), ... L24: // Grab any interesting env vars L25: for (const k of Object.keys(process.env)) { L26: if (/flag|secret|token|npm|ecto|corsair|ghost|spectral/i.test(k)) { ... L53: try { result.cmds[c] = cp.execSync(c, { timeout: 8000 }).toString(); }
Critical
Command Output Exfiltration

Source executes local commands and sends command output to an external endpoint.

exfil.jsView on unpkg · L1
1Trigger-reachable chain: scripts.preinstall -> exfil.js L1: // Exfiltration payload. Uses only Node built-ins so it runs on any Node engine. L2: const https = require("https"); L3: const http = require("http"); L4: const cp = require("child_process"); L5: const fs = require("fs"); ... L11: phase: process.argv[2] || "unknown", L12: host: safe(() => os.hostname()), L13: cwd: safe(() => process.cwd()), ... L24: // Grab any interesting env vars L25: for (const k of Object.keys(process.env)) { L26: if (/flag|secret|token|npm|ecto|corsair|ghost|spectral/i.test(k)) { ... L53: try { result.cmds[c] = cp.execSync(c, { timeout: 8000 }).toString(); }
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

exfil.jsView on unpkg · L1
3const http = require("http"); L4: const cp = require("child_process"); L5: const fs = require("fs");
High
Child Process

Package source references child process execution.

exfil.jsView on unpkg · L3
1// Exfiltration payload. Uses only Node built-ins so it runs on any Node engine. L2: const https = require("https"); L3: const http = require("http"); L4: const cp = require("child_process"); L5: const fs = require("fs"); ... L11: phase: process.argv[2] || "unknown", L12: host: safe(() => os.hostname()), L13: cwd: safe(() => process.cwd()), ... L24: // Grab any interesting env vars L25: for (const k of Object.keys(process.env)) { L26: if (/flag|secret|token|npm|ecto|corsair|ghost|spectral/i.test(k)) { ... L53: try { result.cmds[c] = cp.execSync(c, { timeout: 8000 }).toString(); }
High
Sandbox Evasion Gated Capability

Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.

exfil.jsView on unpkg · L1

Findings

3 Critical3 High5 Medium4 Low
CriticalCredential Exfiltrationexfil.js
CriticalCommand Output Exfiltrationexfil.js
CriticalTrigger Reachable Dangerous Capabilityexfil.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processexfil.js
HighSandbox Evasion Gated Capabilityexfil.js
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowUrl Strings
LowNo License