Summary
The CLI deny-wrapper generator in packages/runtime/src/band-server.ts builds a bash script that runs eval on patterns derived from a BAND.md's deny.cli field. The patterns are escaped for " but not for $, backticks, or other substitution metacharacters, so a malicious BAND.md can execute arbitrary code at wrapper-generation time inside the Lima VM.
Where
packages/runtime/src/band-server.ts:362-374
The wrapper is emitted as:
DENY_PATTERNS=("user-controlled pattern" ...)
for P in "${DENY_PATTERNS[@]}"; do
if eval "[[ \"\$FULL_CMD\" == \$P ]]" 2>/dev/null; then
...
fi
done
Reproduction
A BAND.md with deny.cli: ["foo$(id > /tmp/pwned)*"] causes the wrapper script to contain DENY_PATTERNS=("foo$(id > /tmp/pwned)*"). When bash parses the array assignment, the command substitution executes — as the band-server user, before sandboxing.
Threat model
The attacker is anyone who can author a BAND.md the system loads (malicious skill author, compromised dependency, etc.). Code runs as the host VM user, not band-runner — privilege escalation inside the VM.
Fix sketch
Drop eval. Bash already does glob matching in [[ == $P ]] without it:
for P in "${DENY_PATTERNS[@]}"; do
if [[ "$FULL_CMD" == $P ]]; then ...
done
Alternatively, escape $, backticks, !, and other metacharacters in the pattern array, or restrict deny.cli values to an allowlist of characters at parse time.
Summary
The CLI deny-wrapper generator in
packages/runtime/src/band-server.tsbuilds a bash script that runsevalon patterns derived from a BAND.md'sdeny.clifield. The patterns are escaped for"but not for$, backticks, or other substitution metacharacters, so a malicious BAND.md can execute arbitrary code at wrapper-generation time inside the Lima VM.Where
packages/runtime/src/band-server.ts:362-374The wrapper is emitted as:
Reproduction
A BAND.md with
deny.cli: ["foo$(id > /tmp/pwned)*"]causes the wrapper script to containDENY_PATTERNS=("foo$(id > /tmp/pwned)*"). When bash parses the array assignment, the command substitution executes — as the band-server user, before sandboxing.Threat model
The attacker is anyone who can author a BAND.md the system loads (malicious skill author, compromised dependency, etc.). Code runs as the host VM user, not band-runner — privilege escalation inside the VM.
Fix sketch
Drop
eval. Bash already does glob matching in[[ == $P ]]without it:Alternatively, escape
$, backticks,!, and other metacharacters in the pattern array, or restrict deny.cli values to an allowlist of characters at parse time.