The old rule -- any shell operator disqualifies the whole command -- was wrong
in both directions, verified by running it:
find . -delete -> ALLOW (destructive, no prompt)
find . -exec rm {} + -> ALLOW (destructive, no prompt)
git status && git diff -> ask (two allowed reads, refused)
It judged punctuation rather than danger. `-delete` and `-exec` need no
separator, so a bare `find` prefix auto-ran them; meanwhile two independently
allowed reads were refused for containing `&&`.
Now:
- Constructs whose contents we cannot evaluate -- substitution, redirection,
variable expansion, grouping -- still disqualify the whole command, because
the unexamined tail after a prefix match must only ever be arguments.
- Compound commands are split on &&, ||, ;, |, |&, & and newlines, and EVERY
part must be independently covered by an allowlist entry.
- Parts that run code named in their arguments are never prefix-eligible:
argument executors (xargs, sudo, timeout, env, docker, npx, ssh...),
interpreters carrying inline code (python -c, bash -c, node -e), and
execution/deletion flags (-exec, -execdir, -delete, -ok).
- Matching stays on parsed words, so `git status` covers `git status -s` but
never `git statusfoo` or a bare `git`.
Splitting is textual and does not respect quoted separators. That is
deliberate: over-splitting yields MORE parts to justify, never fewer, so it
cannot loosen a verdict.
37 new tests including metamorphic cases (spacing, quoting, absolute program
path must not loosen `find . -delete`). Golden matrix: three rows flip as
intended, two added. 164 permission tests green.
Design of record: ocw-context/docs/reviewed-auto-mode.md Part 2 (CMD-1/3/4).
Three gate defects, each verified by direct execution before and after.
1. web_fetch was RiskClass.READ, so is_consequential() was False and evaluate()
returned allow on its third rung -- before any rule, mode or PDP, in EVERY
mode including plan/discuss. A URL's query string carries data outbound, so
this was an ungated egress path. New RiskClass.EGRESS covers model-chosen
network reads; web_search stays READ (fixed configured provider, not a
model-chosen host). Adds an allowed_domains allowlist (exact host or
subdomain; 'evil-python.org' never matches 'python.org'), a session-scoped
"always allow this domain" grant, and ApprovalOutcome.ALWAYS_DOMAIN.
2. A risk override could DOWNGRADE a built-in: marking write_file as read made
is_write False (skipping path scoping) and consequential False (skipping the
read-only gate) at once -- one settings line disabling two protections, in
every future session. Overrides may now only tighten a built-in write/exec/
egress tool; relaxing a metadata/MCP tool (the intended use) still works.
3. Path scoping read a literal "path" argument, so apply_patch and
apply_unified_diff -- whose paths live inside the patch/diff blob -- were
never scoped at all. write_paths() extracts them from the blob and scopes
every one; a write whose path cannot be located now fails closed to approval
rather than slipping through auto/custom unscoped.
allowed_domains is user-global only, alongside auto_allow: a cloned repo must
not be able to widen the agent's network reach.
Golden matrix: web_fetch interactive allow->ask, plan allow->deny, plus new
egress/patch rows (31 rows green). test_permissions_risk's override test
asserted the old downgrade behavior and is updated to the tightening rule.
Full suite: 22 failures, all pre-existing on the unmodified tree (boto3 absent,
Windows symlink privilege, Slack socket timeouts) -- none introduced here.
Design of record: ocw-context/docs/reviewed-auto-mode.md Part 3.
Freezes today's evaluate() verdict across 26 (mode, tool, args, grants)
situations, so any later permission change shows up as a row-diff. Four rows
are marked BASELINE-WRONG / BASELINE-ANNOYING on purpose: they record known
gaps (shell auto with no sandbox, find -delete and find -exec auto-allowed via
a find prefix, git status && git diff rejected for the operator, web_fetch
never gating in any mode). The PRs that fix these flip their rows here as the
visible proof.
Design of record: ocw-context/docs/reviewed-auto-mode.md Parts 3 and 7.