Staged Command Approval

Split a compound shell command into stages and resolve each against policy, so only complete, known-safe stages clear automatically, one rejected stage denies the whole command, interpreters never get prefix grants, and a deny always beats an allow.

Evidence: moderate

Approval systems that judge a command by its first word are easy to fool. A pipeline that starts with a harmless grep can end with a deletion, and a standing grant for python approves whatever script follows it. Approving whole command strings, on the other hand, prompts the human for every read-only probe and trains them to click through. This note is about how a human approval gate should read a shell command when the agent has one.

Meta's Muse Code cookbook describes a middle path. The harness parses a compound command into ordered stages, each with its own argument vector and a flag for whether it could be fully parsed. Each stage resolves against policy as known-safe, such as ls, cat or grep, which clears automatically in the default mode, where the agent runs inside the recipe's OS sandbox; dangerous, such as rm -rf even when wrapped in sudo; or unresolved, which is held for review. The first unresolved stage blocks, one rejected stage denies the whole command, and the command runs as a single unit only once every stage has cleared. Stages containing variables, command substitution or writing redirects can never count as known-safe. Trust comes in three scopes: allow once, a workspace rule stored in a policy file, or reject. Prefix rules are refused for interpreter wrappers such as bash, python, env and sudo, because whatever follows them is arbitrary code. Precedence is fixed: deny beats prompt, and prompt beats allow. A stricter untrusted mode prompts for any action without an explicit allow rule, ls included.

Read-only does not mean confidentiality-safe. Auto-clearing cat, grep or ls by command name lets an injected or mistaken agent pull credentials and private files into its context without review, if the shell can reach them. Auto-clear read commands only where the sandbox confines which paths they can read (contain the environment first, with credentials outside the sandbox). Without that confinement, use the prompt-on-unmatched posture.

The evidence is one vendor recipe, but its fail-closed parsing matches Hermes's rule that unparseable commands are refused. It sits in the policy layer of the layered agent permission stack, above an un-overridable hardline command floor, and the decisions it records still need to survive restarts as durable approval state.

How much it matters depends on tool design. An agent that exposes only a narrow action verb set has little to stage, since each verb is approved by name. One that keeps a general shell, as the minimal, general tool surface camp recommends, or keeps a shell only for read-only investigation, can use staged approval to let probes run unattended while any write, restart or interpreter call in the same pipeline waits for a human.


Sources

  • Meta Model API cookbook, Building with Muse Code, undated (retrieved 3 Oct 2026) — https://dev.meta.ai/docs/cookbook/staged-approvals
  • Nous Research official docs as of v0.21.5, fail-closed parsing — https://hermes-agent.nousresearch.com/docs/user-guide/security