Background
The shell tool's allowlist + per-prefix risky-arg demotion (#257, #258) blocks destructive operations, but read-only commands like cat, grep, find, head, tail are still on the fast path with any path argument. The agent can cat ~/.ssh/id_rsa or grep -r AWS_SECRET /etc and pipe the contents straight into the LLM provider's chat context — a real exfiltration vector even on a local CLI.
OWASP AI Agent Cheat Sheet § 8 (Data Protection / Path traversal) and § 1's example config ("blocked_patterns": ["*.env", "*.key", "*.pem", "*secret*"]) frame this as the complement to per-tool least-privilege: not just which command, but against which resources.
Proposal
Path-argument scanner on top of the existing allowlist gate. When a run_command call matches the allowlist and one of its argv tokens resolves into a configured sensitive prefix or matches a sensitive filename pattern, demote it to the confirm gate (same code path as RISKY_ARGS).
Default blocklist (suggested):
- Path prefixes:
~/.ssh, ~/.aws, ~/.gnupg, ~/.kube, /etc/shadow, /etc/sudoers
- Filename patterns:
*.env, *.env.*, *.key, *.pem, id_rsa*, id_ed25519*, *credentials*, *secret*
User-configurable. Case-insensitive on Windows. Tilde expansion + cwd-relative resolution required.
Acceptance criteria
Out of scope
- Output-side scanning (post-execution PII filter on stdout) — separate concern, much larger
- Sandboxing / seccomp / chroot — the local-CLI threat model assumes user trust of the binary, just not of the model
References
Background
The shell tool's allowlist + per-prefix risky-arg demotion (#257, #258) blocks destructive operations, but read-only commands like
cat,grep,find,head,tailare still on the fast path with any path argument. The agent cancat ~/.ssh/id_rsaorgrep -r AWS_SECRET /etcand pipe the contents straight into the LLM provider's chat context — a real exfiltration vector even on a local CLI.OWASP AI Agent Cheat Sheet § 8 (Data Protection / Path traversal) and § 1's example config (
"blocked_patterns": ["*.env", "*.key", "*.pem", "*secret*"]) frame this as the complement to per-tool least-privilege: not just which command, but against which resources.Proposal
Path-argument scanner on top of the existing allowlist gate. When a
run_commandcall matches the allowlist and one of its argv tokens resolves into a configured sensitive prefix or matches a sensitive filename pattern, demote it to the confirm gate (same code path asRISKY_ARGS).Default blocklist (suggested):
~/.ssh,~/.aws,~/.gnupg,~/.kube,/etc/shadow,/etc/sudoers*.env,*.env.*,*.key,*.pem,id_rsa*,id_ed25519*,*credentials*,*secret*User-configurable. Case-insensitive on Windows. Tilde expansion + cwd-relative resolution required.
Acceptance criteria
SENSITIVE_PATHSconfig layer (default list + user override)src/tools/shell.tsthat flags any argv token resolving into the blocklistRISKY_ARGS(chains + confirm gate work uniformly)~/-relative paths, cwd-relative paths, glob patterns, case-insensitive on win32./src/.env.exampleshould still trigger (we do not want the agent reading.env-shaped files at all)Out of scope
References
git branch -dbypasses review mode #257, fix(shell): demote destructive flags on allowlisted commands #258