Agent safety / 05 OCT 2026

Make the shell rule catch the whole command.

A deny rule that catches rm in one position and misses it after an assignment or inside a compound command is a label, not a brake.

The command line has joints

A shell command is not one flat string. Bash identifies assignments and redirections before expansion. It can join commands with operators, put them in groups, and pass them through wrappers. A permission matcher has to preserve the command that matters while it reads that structure.

Claude Code's permission documentation says compound commands are split into separate commands for matching. The same page warns that wrappers can hide the command behind them. Release 2.1.289 fixed cases involving an expanded environment-variable prefix, a bare assignment before a command, and a nested part of a compound command.

Do not test the rule with the clean command. Test every place the command can hide.

This is not a reason to abandon shell permissions. It is a reason to treat the rule set like code. Pin the agent version. Keep a small pack of commands that must ask or stop. Run it after upgrades, settings changes, and sandbox changes.

Start with one destructive verb

If policy should block rm -rf build, test that exact action alone, after an assignment, after an allowed command, inside a group, and behind each wrapper your team permits. Add the observed prompt or refusal to the receipt.

Interactive replacement for a flat allow list

Shell policy clutch

Select a fixture, inspect the joints, and prepare a negative-test receipt. This teaching bench does not run commands or reproduce Claude Code's parser.

Command fixtures

Choose a shell command fixture

Review path

rm -rf build
Illustrative shell partsDirect command
EXPECTED GATE: ASK OR DENYThe destructive command is visible at the first command position.
Test specification0 / 4

Version fixes do not replace your fixture pack

The release note says these matching bugs were fixed. It does not say every possible wrapper, expansion, or shell dialect now behaves the way your organization expects. The official permissions guide lists boundaries that rules do not match, including commands hidden behind wrappers such as bash -c.

Keep the fixture pack narrow enough to run after every upgrade. Cover the denied verb, each approved wrapper, every permission mode you use, and one command that should still pass. Run destructive fixtures only in a disposable directory with no credentials and no valuable parent path.

The final record needs the agent version, settings source, selected mode, exact command, expected decision, observed decision, and captured output. Four checked boxes below mean the template has its sections. They do not prove that a policy passed.