Back to Intelligence

MALFEX Campaign: Malicious npm Package 'imgdecode' Hides Shellcode Loader in Windows Native Addon — Detection and Response Guide

SA
Security Arsenal Team
October 17, 2026
13 min read

Security researchers have disclosed a new software supply chain campaign dubbed MALFEX, and one of its confirmed components is a malicious npm package named imgdecode. Published to the npm registry on September 30, 2026 by the user malfexteste8, the package masquerades as an image decoding utility while concealing a shellcode loader inside a Windows native addon (a compiled .node binary module). As of the reporting, the package had been downloaded 979 times and was still live on the registry.

This is not a theoretical risk. Every download represents a developer workstation, a CI/CD build agent, or a production container that may have executed attacker-controlled shellcode. Native addons are a particularly insidious delivery vehicle: they bypass the JavaScript-level static analysis most security tooling performs on npm packages, they execute with the full privileges of the Node.js process, and they blend into the legitimate node-gyp/prebuild-install ecosystem that thousands of trustworthy packages rely on.

If your organization builds Node.js applications — and statistically, it does — you need to answer three questions today: Did imgdecode enter our dependency tree? Did its install-time or runtime code execute? And can we prevent the next one?

Technical Analysis

What We Know About the Package

  • Package name: imgdecode (npm registry)
  • Published: September 30, 2026
  • Publisher account: malfexteste8
  • Download count: 979 (at time of reporting)
  • Status: Still available on npm at time of reporting — do not assume registry takedown has occurred
  • Campaign attribution: MALFEX, a recently disclosed software supply chain attack campaign
  • Payload delivery: Shellcode loader embedded in a Windows native addon (compiled .node module loaded via Node.js N-API/require() bindings)

How the Attack Works — Defender's View of the Kill Chain

The tradecraft here follows a pattern we've watched mature across npm supply chain incidents, with a meaningful escalation: the payload is native code, not obfuscated JavaScript.

  1. Package publication and social proof. A benign-sounding utility package (imgdecode implies image decoding — a plausible dependency for web apps, thumbnail services, or asset pipelines) is published under a throwaway maintainer account. Typosquatting-adjacent naming and dependency confusion are the typical vectors for initial inclusion in a victim's package.json, either directly or as a transitive dependency.

  2. Install-time execution. Malicious npm packages almost universally weaponize lifecycle scripts (preinstall, install, postinstall) in package.json. These scripts run automatically during npm install with the installing user's privileges — on developer laptops, on build agents, and inside containers. This is where the loader stages or activates the native addon.

  3. Native addon loading. The package ships a precompiled .node binary (or compiles one at install time via node-gyp). When the package is require()'d, Node.js loads this binary directly into the node.exe process address space. There is no JavaScript to audit — the malicious logic exists only as compiled machine code.

  4. Shellcode execution. The native addon acts as a shellcode loader: it allocates executable memory (classic VirtualAlloc → VirtualProtect → execution flow, or thread-injection variants), writes embedded or downloaded shellcode, and executes it in-process. Because execution occurs inside the legitimate, often trusted node.exe process, it inherits that process's reputation with EDR and application allowlisting solutions.

  5. Post-exploitation. Shellcode loaders in supply chain campaigns typically deliver credential harvesters (browser stores, SSH keys, cloud CLI tokens, .npmrc and .env files — all high-value on developer machines), second-stage C2 implants, or persistence mechanisms. Developer workstations are crown-jewel targets precisely because they hold the keys to source code, build signing, and production deployment.

Why Native Addons Defeat Common Controls

  • Static analysis blind spot: Most npm security scanners (including default npm audit and many SCA tools) analyze JavaScript. A compiled .node binary is opaque to them.
  • Process masquerading: Malicious activity executes as node.exe, a process most EDR policies treat as developer-normal.
  • Legitimate ecosystem cover: Thousands of genuine packages (sharp, bcrypt, sqlite3, canvas) ship native addons via prebuild-install or node-gyp, so the presence of a .node file is not inherently anomalous. Detection must focus on behavior: who loads it, from where, and what the process does afterward.

Exploitation Status

  • In-the-wild distribution: Confirmed — 979 downloads from the live npm registry.
  • Active campaign: Yes — part of the MALFEX campaign, disclosed October 2026.
  • CVE: None assigned (malicious package, not a vulnerability). No CISA KEV entry applies.
  • Registry status: Still available at time of reporting — treat any environment that resolves npm packages as potentially exposed until takedown and cache propagation are confirmed.

Detection & Response

The detections below target the observable behaviors of this threat class: native addon loading from suspicious paths, Node.js processes exhibiting loader-like child process and command-line behavior, and lifecycle-script execution spawning unexpected binaries. These are tuned to be high-signal — the baseline rule is node.exe spawning shells or LOLBins, which is almost never legitimate outside of actively debugged build tooling.

Sigma Rules

YAML
---
title: Node.js Process Spawning Shell or LOLBin - Potential npm Supply Chain Payload
transactionId: 8f2c4a91-3b7d-4e5a-9c1f-2d6e8a0b4f71
id: 8f2c4a91-3b7d-4e5a-9c1f-2d6e8a0b4f71
status: experimental
description: Detects node.exe spawning command shells, script interpreters, or Windows LOLBins. Malicious npm packages such as MALFEX's 'imgdecode' execute shellcode loaders and staging commands from within the Node.js process during install lifecycle scripts or native addon execution. Rarely legitimate outside of interactive debugging.
references:
  - https://thehackernews.com/2026/10/malfex-npm-package-imgdecode-hides.html
  - https://attack.mitre.org/techniques/T1195/002/
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/10/03
tags:
  - attack.supply_chain_compromise
  - attack.t1195.002
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\node.exe'
      - '\npm.cmd'
      - '\npx.cmd'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\rundll32.exe'
      - '\regsvr32.exe'
      - '\mshta.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\curl.exe'
      - '\certutil.exe'
      - '\bitsadmin.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Legitimate build tooling invoking scripts during node-gyp compilation (correlate with node-gyp in command line)
  - Developer debugging sessions
level: high
---
title: Native Node Addon Loaded From Suspicious Path
transactionId: 4d1e7b23-9a6c-4f82-b3d5-7e0c1a9f8254
id: 4d1e7b23-9a6c-4f82-b3d5-7e0c1a9f8254
status: experimental
description: Detects image load events where a .node native addon binary is loaded from user-writable or temporary locations instead of a standard node_modules tree. The MALFEX 'imgdecode' package stages a shellcode loader inside a compiled .node addon; staging it to temp paths is a common evasion pattern.
references:
  - https://thehackernews.com/2026/10/malfex-npm-package-imgdecode-hides.html
  - https://attack.mitre.org/techniques/T1195/002/
  - https://attack.mitre.org/techniques/T1129/
author: Security Arsenal
date: 2026/10/03
tags:
  - attack.supply_chain_compromise
  - attack.t1195.002
  - attack.execution
  - attack.t1129
logsource:
  category: image_load
  product: windows
detection:
  selection:
    ImageLoaded|endswith: '.node'
  filter_paths:
    ImageLoaded|contains: '\node_modules\'
  condition: selection and not filter_paths
falsepositives:
  - Portable or self-contained Electron applications bundling addons outside node_modules
  - Custom enterprise packaging of native modules
level: medium
---
title: npm Lifecycle Script Spawning Download or Execution Tooling
transactionId: b7a3f5c8-2e94-4d61-a8c2-5f0e7b3d9168
id: b7a3f5c8-2e94-4d61-a8c2-5f0e7b3d9168
status: experimental
description: Detects processes spawned under npm/node install chains that invoke download cradles, encoded commands, or direct binary execution. Malicious packages like 'imgdecode' abuse preinstall/postinstall lifecycle hooks to stage native loaders and retrieve second-stage payloads.
references:
  - https://thehackernews.com/2026/10/malfex-npm-package-imgdecode-hides.html
  - https://attack.mitre.org/techniques/T1195/002/
  - https://attack.mitre.org/techniques/T1105/
author: Security Arsenal
date: 2026/10/03
tags:
  - attack.supply_chain_compromise
  - attack.t1195.002
  - attack.command_and_control
  - attack.t1105
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentCommandLine|contains:
      - 'npm install'
      - 'npm ci'
      - 'node-gyp'
      - 'prebuild-install'
      - 'preinstall'
      - 'postinstall'
  selection_suspicious:
    CommandLine|contains:
      - 'Invoke-WebRequest'
      - 'Invoke-Expression'
      - 'IEX'
      - 'FromBase64String'
      - ' -enc '
      - ' -e '
      - 'DownloadString'
      - 'VirtualAlloc'
      - 'certutil -decode'
      - 'curl.exe http'
  condition: selection_parent and selection_suspicious
falsepositives:
  - Legitimate packages downloading prebuilt binaries from official release endpoints (allowlist known-good hosts such as github.com release assets for approved packages)
level: high

KQL — Microsoft Sentinel / Defender

This query hunts for the core behavioral signature — Node.js or npm install chains spawning shells, LOLBins, or encoded/download cradles — plus file artifacts consistent with the imgdecode package landing on disk. Run it across developer workstations and build agents first; that is where supply chain malware concentrates.

KQL — Microsoft Sentinel / Defender
let Lookback = 14d;
let SuspiciousChildren = dynamic([
  "cmd.exe", "powershell.exe", "pwsh.exe", "rundll32.exe", "regsvr32.exe",
  "mshta.exe", "wscript.exe", "cscript.exe", "curl.exe", "certutil.exe",
  "bitsadmin.exe", "wmic.exe"
]);
let NodeProcesses = DeviceProcessEvents
| where Timestamp > ago(Lookback)
| where InitiatingProcessFileName in~ ("node.exe", "npm.cmd", "npx.cmd", "node")
     or InitiatingProcessCommandLine has_any ("npm install", "npm ci", "node-gyp", "prebuild-install", "postinstall", "preinstall");
let SuspiciousExec = NodeProcesses
| where FileName in~ (SuspiciousChildren)
     or ProcessCommandLine has_any ("FromBase64String", "Invoke-Expression", "IEX", "DownloadString", "VirtualAlloc", "certutil -decode", " -enc ")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, SHA256, ReportId;
let ImgdecodeArtifacts = DeviceFileEvents
| where Timestamp > ago(Lookback)
| where FolderPath has_any ("imgdecode", "malfex")
     or (FileName endswith ".node" and FolderPath !has "node_modules")
| project Timestamp, DeviceName, InitiatingProcessFileName, FolderPath, FileName, SHA256, ReportId;
union SuspiciousExec, ImgdecodeArtifacts
| order by Timestamp desc

If your environment ingests Sysmon or CEF logs into Sentinel instead of Defender tables, the same logic ports directly: filter SecurityEvent/CommonSecurityLog for node.exe as parent with the same child-process and command-line indicator sets.

Velociraptor VQL

Use this artifact for fleet-wide scoping: it enumerates running Node.js processes and their command lines, then sweeps common module installation paths for the imgdecode package directory and recently created native addon binaries outside standard trees. Deploy it as a hunt across your developer and build infrastructure.

VQL — Velociraptor
-- MALFEX imgdecode supply chain scoping artifact
-- 1. Enumerate node/npm processes and command lines
LET procs = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Name =~ 'node|npm|npx'
   OR CommandLine =~ 'imgdecode|node-gyp|prebuild-install'

-- 2. Find imgdecode package directories and suspicious .node binaries
LET hits = SELECT FullPath, Size, Mtime, Btime
FROM glob(globs=[
  'C:/Users/*/**/node_modules/imgdecode/**',
  'C:/Program Files/**/node_modules/imgdecode/**',
  'C:/**/node_modules/imgdecode/package.json',
  'C:/Users/*/AppData/Local/Temp/**/*.node',
  'C:/Windows/Temp/**/*.node',
  'C:/ProgramData/**/*.node'
])
WHERE NOT FullPath =~ 'node_modules'
   OR FullPath =~ 'imgdecode'

SELECT * FROM procs
UNION ALL
SELECT NULL AS Pid, NULL AS Ppid, 'FILE_HIT' AS Name,
       FullPath AS CommandLine, NULL AS Exe, NULL AS Username,
       Mtime AS CreateTime
FROM hits

Remediation & Scoping Script

Run this PowerShell script on developer workstations and build agents to determine exposure, remove the malicious package, and harden npm against lifecycle-script abuse. Adapt the search root for your environment's project locations.

PowerShell
# MALFEX 'imgdecode' exposure check and remediation - run as Administrator where possible
$ErrorActionPreference = 'SilentlyContinue'
$SearchRoots = @("$env:USERPROFILE\source", "$env:USERPROFILE\repos", "$env:USERPROFILE\projects", "C:\builds", "C:\agent\_work")
$ReportPath = "$env:TEMP\imgdecode_exposure_report.txt"
"MALFEX imgdecode exposure scan - $(Get-Date)" | Out-File $ReportPath

# 1. Search dependency manifests and lockfiles for the malicious package
foreach ($root in $SearchRoots) {
    if (Test-Path $root) {
        Get-ChildItem -Path $root -Recurse -Include 'package.json','package-lock.json','yarn.lock','pnpm-lock.yaml' -ErrorAction SilentlyContinue |
            Select-String -Pattern 'imgdecode' -List |
            ForEach-Object { "[EXPOSED] $($_.Path)" | Out-File $ReportPath -Append }
    }
}

# 2. Detect installed package artifacts on disk
foreach ($root in $SearchRoots) {
    if (Test-Path $root) {
        Get-ChildItem -Path $root -Recurse -Directory -Filter 'imgdecode' -ErrorAction SilentlyContinue |
            ForEach-Object { "[INSTALLED] $($_.FullName)" | Out-File $ReportPath -Append }
    }
}

# 3. Check global npm installations and npm cache
npm ls -g imgdecode 2>$null | Out-File $ReportPath -Append
Get-ChildItem "$env:LOCALAPPDATA\npm-cache" -Recurse -Filter '*imgdecode*' -ErrorAction SilentlyContinue |
    ForEach-Object { "[CACHE] $($_.FullName)" | Out-File $ReportPath -Append }

# 4. Flag stray native addons outside node_modules (loader staging indicator)
foreach ($p in @("$env:TEMP", "C:\Windows\Temp", "C:\ProgramData")) {
    Get-ChildItem -Path $p -Recurse -Filter '*.node' -ErrorAction SilentlyContinue |
        ForEach-Object { "[STRAY-ADDON] $($_.FullName) created $($_.CreationTime)" | Out-File $ReportPath -Append }
}

# 5. If exposed: remove package and force clean reinstall with scripts disabled
$exposed = Select-String -Path $ReportPath -Pattern '\[EXPOSED\]|\[INSTALLED\]' -Quiet
if ($exposed) {
    "[!] EXPOSURE DETECTED - treating host as compromised, see IR steps below" | Out-File $ReportPath -Append
    # In each affected project directory, run manually after credential rotation:
    #   npm uninstall imgdecode
    #   npm cache clean --force
    #   Remove-Item -Recurse -Force node_modules, package-lock.json
    #   npm install --ignore-scripts
}

# 6. Harden npm globally: disable lifecycle scripts by default (breaks this attack class)
npm config set ignore-scripts true --location=user
"[HARDENED] ignore-scripts=true set for user $($env:USERNAME)" | Out-File $ReportPath -Append

Get-Content $ReportPath

Note the deliberate design choice in step 5: the script reports and hardens but does not auto-remediate an exposed host. If imgdecode executed on a machine, uninstalling the package does nothing for the shellcode that already ran. That host is an IR case, not a cleanup task.

Remediation

1. Scope exposure immediately (today).

  • Search all package.json, package-lock.json, yarn.lock, and pnpm-lock.yaml files across source control and build systems for imgdecode. Check transitive dependencies — a lockfile grep is the reliable method, not package.json review alone.
  • Query your artifact registry/proxy (Artifactory, Nexus, Verdaccio, GitHub Packages) for cached copies of imgdecode and purge them. Registry takedown does not clear internal caches.
  • Review CI/CD pipeline logs for builds that fetched the package after September 30, 2026.

2. Treat every execution as a compromise. Any host that ran npm install against a dependency tree containing imgdecode executed attacker shellcode with that user's privileges. Standard IR procedure applies:

  • Isolate the host; capture memory and disk images before remediation if forensics capacity allows.
  • Rotate every credential the user context could reach: browser-stored credentials, SSH private keys, cloud provider tokens (~/.aws, ~/.azure, gcloud credentials), .npmrc auth tokens, .env files, and any CI secrets present on build agents. Assume exfiltration.
  • Hunt the host with the Sigma/KQL/VQL content above for loader follow-on activity: persistence, C2 egress from node.exe, and credential-access artifacts.

3. Structural hardening against this attack class.

  • Disable lifecycle scripts by default (ignore-scripts=true in user and CI .npmrc), then explicitly allowlist the small set of packages that legitimately need them. This single control breaks the install-time execution stage of the majority of malicious npm packages.
  • Pin dependencies and enforce lockfile integrity in CI (npm ci with immutable lockfiles, hash verification). Block floating version ranges on security-critical build agents.
  • Route all npm traffic through an internal proxy/registry with malware screening (e.g., an SCA gateway that quarantines newly published packages for a cooling-off period — imgdecode was weaponized from day one; a 7-14 day embargo on brand-new packages from brand-new publishers would have blocked it entirely).
  • Audit native addon usage. Maintain an allowlist of packages permitted to ship or compile .node binaries in your environment. Alert on anything new loading a native module — that is precisely the signal this campaign generates.
  • Apply least privilege to build agents. Build runners should hold short-lived, scoped credentials only. The blast radius of a malicious install script is defined by what the installing identity can reach.

4. Registry and ecosystem actions.

  • Report and monitor npm's security advisory feed for the formal imgdecode takedown notice; until confirmed removed, treat the package as live and downloadable.
  • Add imgdecode and the publisher malfexteste8 to internal blocklists at the proxy layer, and monitor for MALFEX campaign sibling packages — supply chain actors publish in batches, and imgdecode is unlikely to be the only package.

There is no vendor patch for a malicious package — the fix is removal, credential rotation, and the structural controls above. The organizations that absorb supply chain hits with the least damage are the ones that made malicious package execution technically hard before the package ever shipped.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.