Back to Intelligence

npm Supply Chain Attack: Six Malicious Packages Resolved C2 Servers via Ethereum Wallet — Detection and Remediation Guide

SA
Security Arsenal Team
August 13, 2026
10 min read

Security researchers have disclosed a campaign in which six malicious npm packages embedded a novel command-and-control (C2) resolution mechanism: instead of hardcoding C2 domains or IP addresses, the malware queries the Ethereum blockchain — specifically data associated with an attacker-controlled wallet — to dynamically locate its C2 infrastructure.

This is a meaningful escalation in supply-chain tradecraft. By storing C2 pointers on a public, immutable, globally replicated ledger, the attacker gains a resilient, takedown-resistant "dead drop" for infrastructure rotation. Defenders cannot seize the blockchain, cannot sinkhole a wallet address, and cannot rely on static blocklists to keep pace — the C2 destination can change the moment the attacker publishes a new transaction.

If your organization builds JavaScript/TypeScript applications, runs CI/CD pipelines that execute npm install, or has developers pulling packages from the public npm registry, you are in the blast radius of this technique. This post breaks down how the attack works, how to hunt for it, and how to harden your dependency pipeline against it.

How the Ethereum-Based C2 Resolution Works

The disclosed packages follow the now-familiar malicious npm playbook — typosquatting or benign-looking utility packages with hostile logic staged in lifecycle hooks (preinstall, install, postinstall) or obfuscated module code — but with a critical twist in the C2 stage:

  1. Delivery: A developer or build agent installs the package via npm install. Malicious code executes automatically through an install-time lifecycle script or upon first require()/import of the module.
  2. C2 resolution via blockchain: Instead of reaching out to a hardcoded domain, the malware issues read-only queries against the Ethereum network — typically through public JSON-RPC gateways or API services (e.g., Infura, Alchemy, Etherscan-style APIs, or cloudflare-eth.com) — reading transaction data or contract state tied to an attacker-controlled wallet address.
  3. Decoding: The retrieved data (transaction input fields, contract storage, or wallet-associated metadata) is decoded to extract the current C2 URL or IP. This is functionally identical to the classic "dead drop resolver" technique (MITRE ATT&CK T1102.001 — Web Service: Dead Drop Resolver), but the dead drop is an immutable public ledger.
  4. Tasking: With a live C2 address in hand, the malware beacons out, pulls second-stage payloads, and — consistent with recent npm campaigns — typically targets developer secrets: environment variables, .env files, npm/GitHub/cloud tokens, SSH keys, and crypto wallet data.

Why defenders should take this seriously

  • Takedown resistance: You cannot get a blockchain delisted. Traditional domain seizure and registrar abuse workflows are irrelevant for the resolution layer.
  • Evasion of reputation-based controls: Public Ethereum RPC endpoints are legitimate, high-reputation infrastructure. Egress to *.infura.io or an Etherscan API will sail past most domain-reputation filters — and in organizations with Web3 development teams, it may be entirely normal traffic.
  • Low-cost infrastructure rotation: The attacker updates the C2 pointer with a single transaction. Static IOC lists go stale immediately.
  • Blast radius through the pipeline: Malicious lifecycle scripts run with the privileges of whatever executed npm install — a developer workstation, or worse, a CI runner holding deployment credentials and signing keys.

Exploitation status: These packages were live on the public npm registry and available for download prior to disclosure and removal. Treat any environment that installed the affected packages as compromised, not merely "exposed."

Detection & Response

The durable detections here are behavioral, not hash-based: (1) install-time script execution under npm/node, and (2) Node.js processes — which have no business doing blockchain lookups in most environments — reaching out to Ethereum RPC/API infrastructure.

Sigma Rules

YAML
---
title: Script Interpreter or Download Cradle Spawned by npm or Node During Install
id: 3f8a2c1d-7e94-4b56-a912-6c4d8e5f0a21
status: experimental
description: Detects script interpreters and download tools spawned as children of npm/node processes, consistent with malicious package lifecycle hooks (preinstall/postinstall) used in the Ethereum-C2 npm supply chain campaign.
references:
  - https://www.infosecurity-magazine.com/news/npm-packages-ethereum-wallet-c2/
  - https://attack.mitre.org/techniques/T1195/002/
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/02/09
tags:
  - attack.execution
  - attack.t1059
  - attack.t1195.002
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\node.exe'
      - '\npm.exe'
      - '\npm.cmd'
      - '\npx.cmd'
      - '\yarn.cmd'
      - '\pnpm.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\curl.exe'
      - '\certutil.exe'
      - '\bitsadmin.exe'
      - '\mshta.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Legitimate build tooling and node-gyp native module compilation
  - Frameworks that legitimately shell out during install (e.g., esbuild, puppeteer)
level: high
---
title: Node.js Process Contacting Ethereum RPC or Blockchain API Endpoints
id: 8b1e4f27-3d6a-4c85-bf19-2a7d5e9c1043
status: experimental
description: Detects node/npm processes establishing network connections to public Ethereum JSON-RPC gateways or blockchain explorer APIs. Malicious npm packages used this channel to resolve C2 infrastructure from an attacker-controlled Ethereum wallet.
references:
  - https://www.infosecurity-magazine.com/news/npm-packages-ethereum-wallet-c2/
  - https://attack.mitre.org/techniques/T1102/001/
author: Security Arsenal
date: 2026/02/09
tags:
  - attack.command_and_control
  - attack.t1102.001
logsource:
  category: network_connection
  product: windows
detection:
  selection_image:
    Image|endswith:
      - '\node.exe'
      - '\npm.exe'
  selection_dest:
    DestinationHostname|contains:
      - 'infura.io'
      - 'alchemyapi.io'
      - 'alchemy.com'
      - 'etherscan.io'
      - 'cloudflare-eth.com'
      - 'quicknode.com'
      - 'ankr.com'
      - 'blastapi.io'
      - 'chainstack.com'
      - 'getblock.io'
  condition: selection_image and selection_dest
falsepositives:
  - Legitimate Web3/blockchain development on developer workstations
  - Build agents compiling projects with web3/ethers dependencies
level: medium
---
title: Suspicious Child Process of npm Install on Linux Build Systems
id: 5c2d9a81-4f73-4e18-bd36-9e1b7c3a8054
status: experimental
description: Detects shells, interpreters, or network tools spawned by npm/yarn/pnpm on Linux developer workstations and CI runners, consistent with malicious package lifecycle script execution observed in the Ethereum-C2 npm campaign.
references:
  - https://www.infosecurity-magazine.com/news/npm-packages-ethereum-wallet-c2/
  - https://attack.mitre.org/techniques/T1195/002/
author: Security Arsenal
date: 2026/02/09
tags:
  - attack.execution
  - attack.t1059.004
  - attack.t1195.002
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentCommandLine|contains:
      - 'npm install'
      - 'npm ci'
      - 'npm i '
      - 'yarn install'
      - 'pnpm install'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/python'
      - '/python3'
      - '/perl'
      - '/base64'
  condition: selection_parent and selection_child
falsepositives:
  - Native module builds (node-gyp) invoking compilers and configure scripts
  - Legitimate packages with install scripts (audit and allowlist per-repository)
level: high

KQL (Microsoft Sentinel / Defender)

Hunt Node.js processes talking to Ethereum infrastructure, and lifecycle-script child processes under package managers:

KQL — Microsoft Sentinel / Defender
// Hunt: Node.js processes reaching Ethereum RPC / blockchain API endpoints
let EthEndpoints = dynamic(["infura.io", "alchemy.com", "alchemyapi.io", "etherscan.io", "cloudflare-eth.com", "quicknode.com", "ankr.com", "blastapi.io", "getblock.io", "chainstack.com"]);
let EthNet =
    DeviceNetworkEvents
    | where TimeGenerated > ago(7d)
    | where InitiatingProcessFileName has_any ("node.exe", "node", "npm", "npm.cmd")
    | where RemoteUrl has_any (EthEndpoints) or RemoteName has_any (EthEndpoints)
    | project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteName, RemoteIP, InitiatingProcessAccountName;
// Correlate with install-time child process execution on the same hosts
let SuspiciousInstalls =
    DeviceProcessEvents
    | where TimeGenerated > ago(7d)
    | where InitiatingProcessFileName has_any ("node.exe", "node", "npm.cmd", "npm", "yarn", "pnpm")
    | where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "curl.exe", "wget", "bash", "sh", "python", "python3", "mshta.exe", "wscript.exe")
    | project InstallTime=TimeGenerated, DeviceName, ChildProcess=FileName, ProcessCommandLine, InitiatingProcessCommandLine, AccountName;
EthNet
| join kind=leftouter SuspiciousInstalls on DeviceName
| extend HostHasSuspiciousInstall = iff(isnotempty(ChildProcess), "YES - investigate", "no")
| sort by TimeGenerated desc

Velociraptor VQL

Use this artifact across developer workstations and build agents to surface Node processes with blockchain/C2 indicators and live connections to RPC endpoints:

VQL — Velociraptor
-- Hunt: Node/npm processes with Ethereum C2 indicators or suspicious children
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE (Name =~ '(?i)node|npm'
   AND CommandLine =~ '(?i)ethers|web3|infura|etherscan|alchemy|eth_call|eth_getBalance|getTransaction')
   OR (Name =~ '(?i)cmd|powershell|pwsh|curl|wget|bash|sh'
   AND CommandLine =~ '(?i)node_modules|npm|postinstall|preinstall')
VQL — Velociraptor
-- Hunt: Established connections from node processes to blockchain RPC infrastructure
SELECT Pid, Name, Path, Status,
       Laddr.IP AS LocalIP, Laddr.Port AS LocalPort,
       Raddr.IP AS RemoteIP, Raddr.Port AS RemotePort
FROM netstat()
WHERE Name =~ '(?i)node'
  AND Status =~ 'ESTAB'
  AND Raddr.Port =~ '443|8545|8546'

Follow up any hits by pulling reverse DNS on the remote IPs and triaging the installed package tree on that host (see remediation script below).

Triage and Remediation Script

Run this Bash script on developer workstations, CI runners, and build containers to audit for malicious lifecycle hooks and blockchain-resolution indicators in installed dependencies:

Bash / Shell
#!/bin/bash
# audit-node-modules.sh - Hunt malicious npm lifecycle hooks and Ethereum C2 resolvers
# Run from the repository root (or point SEARCH_ROOT at your monorepo/build cache)

SEARCH_ROOT="${1:-.}"
echo "=== [1/4] Packages with install-time lifecycle hooks (highest risk) ==="
find "$SEARCH_ROOT" -name "package.json" -path "*/node_modules/*" 2>/dev/null | while read -r f; do
  if grep -qE '"(preinstall|install|postinstall)"' "$f"; then
    echo "[!] $f"
    grep -E '"(preinstall|install|postinstall)"' "$f"
  fi
done

echo ""
echo "=== [2/4] Blockchain/web3 references inside dependencies ==="
grep -rliE 'etherscan|infura|alchemy|cloudflare-eth|eth_call|getTransactionCount|web3\.eth|ethers\.providers' \
  "$SEARCH_ROOT"/node_modules 2>/dev/null | head -50

echo ""
echo "=== [3/4] Obfuscation red flags (eval, base64 blobs, Function constructor) ==="
grep -rlE 'eval\(|new Function|atob\(|Buffer\.from\([^)]*base64' \
  "$SEARCH_ROOT"/node_modules --include="*.js" 2>/dev/null | head -50

echo ""
echo "=== [4/4] Lockfile vs registry integrity check ==="
if [ -f package-lock.json ]; then
  npm audit --audit-level=high
  echo "Tip: diff package-lock.json against a known-good copy in git history."
fi

echo ""
echo "ACTIONS if hits are found:"
echo " 1. Isolate the host from the network (do NOT just delete node_modules)."
echo " 2. Capture memory/disk artifacts before cleanup - secrets may already be staged."
echo " 3. Identify the exact package@version and report to npm security + your IR team."
echo " 4. Rotate ALL credentials present on the host (see Remediation section)."
echo " 5. Rebuild from clean: rm -rf node_modules && npm ci --ignore-scripts"

Remediation and Hardening

If you installed an affected package:

  1. Assume compromise. Malicious install scripts run before you ever import the module. Isolate the affected host or CI runner immediately.
  2. Rotate every secret the host could touch: npm tokens, GitHub/GitLab PATs, cloud provider keys (AWS/Azure/GCP), SSH keys, .env contents, kubeconfigs, and any CI/CD pipeline secrets. Revoke and reissue — do not assume the attacker missed them.
  3. Rebuild clean: rm -rf node_modules && npm ci --ignore-scripts from a reviewed package-lock.json. Do not reuse cached artifacts from the compromised build.
  4. Audit downstream artifacts: If the compromised build produced deployed code, containers, or published internal packages, treat those artifacts as suspect and rebuild from source.

Pipeline hardening (do this regardless):

  • Disable lifecycle scripts by default: Run npm ci --ignore-scripts in CI and set ignore-scripts=true in a committed .npmrc. Explicitly allowlist the small set of packages that genuinely need install scripts (e.g., via @lavamoat/allow-scripts).
  • Enforce lockfiles: Commit package-lock.json, use npm ci (never bare npm install) in automation, and require PR review for any lockfile diff — a one-line lockfile change is how malicious versions get smuggled in.
  • Deploy SCA with malware detection: Socket, Phylum, GitHub Dependabot/npm audit, or equivalent tooling that flags install scripts, obfuscation, and newly published versions — not just known CVEs.
  • Private registry proxy: Route all installs through an internal registry (Artifactory/Nexus/Verdaccio) with a quarantine policy on new package versions — a 7–14 day delay on fresh publishes defeats the majority of malicious-package campaigns, which are typically removed within days of publication.
  • Egress control on build infrastructure: CI runners and build agents should have a strict egress allowlist (npm registry, artifact stores, required APIs). Alert on any egress from build systems to blockchain RPC endpoints (Infura, Alchemy, Etherscan, public Ethereum gateways) — this traffic is almost never legitimate outside Web3 shops.
  • Least privilege for CI: No long-lived production credentials on build runners. Use OIDC-based short-lived credentials and scoped deploy tokens.
  • Pin and vet: Pin exact versions (no ^/~ for sensitive dependency trees), and apply heightened scrutiny to packages with low download counts, single maintainers, or recent maintainer changes.

The Bottom Line

Blockchain-based C2 resolution turns a public good — Ethereum's resilience and censorship resistance — into attacker infrastructure. You cannot take down the dead drop, so you must own the edges you control: what enters your dependency tree, what scripts are allowed to execute at install time, and where your build systems are allowed to talk. Behavioral detection on install-time execution and anomalous Node.js egress will outlast any IOC list for this campaign.

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.