SHELL TOOL · POLICY BEFORE EXECUTION

Agent shell execution: restrict commands before they run

Six commands proposed by an agent meet a denylist, an executable allowlist or validated arguments, run through a shell or as an argument vector.

Computed experiment · sixty inspection seconds

Your experiment

The agent needs git status and the team guide docs/curl-guide.md. It also proposes deleting a build tree, reading a CSV and then posting /etc/passwd away, writing an SSH key through a git flag, and deleting a database from Python. Start with the denylist and try each policy, execution mode and path check.

Play replays the computed run over sixty inspection seconds; Next event steps, Restart rewinds, Speed changes the pace and Inspection time scrubs. Any input change recomputes the run and rewinds it without autoplay.

Event trace

    Computed data

    Final metrics

    Decision model only: nothing is executed. Policies are matched against the proposed command text exactly as shown; the path check looks for absolute paths in the arguments. Real shell tools also need an unprivileged user, a read-only or scratch file system, resource limits, no network by default and an audit log; see the readings.

    Six proposals, two that are needed

    The agent proposes six commands: C1 git status and C2 cat docs/curl-guide.md are needed; C3 deletes a build tree, C4 reads a CSV and then posts /etc/passwd to an outside host, C5 overwrites an SSH key file through the git flag --output, and C6 deletes a database through a Python one-liner. The opening denylist rejects any command containing rm or curl. It stops C3 and C4, but also the needed C2, because the guide’s file name contains curl, and it lets C5 and C6 run: 2 harmful commands ran and 1 needed command was blocked.

    Allowlist executables, then remove the shell

    Set Command policy to Allow executables git, ls and cat. C3 and C6 are refused because rm and python3 are not on the list, and C2 runs. But C4 starts with cat, so the whole string reaches sh -c and the curl after the semicolon runs too, and C5 is plain git: 2 harmful commands. How an allowed command runs matters here: with Argument vector, no shell, the semicolon is just a character in an argument, cat reports missing files and no second program starts, leaving 1 harmful command, C5.

    Allowed programs can still do harm

    C5 never leaves git, yet it writes outside the workspace. Check Path arguments must stay inside the workspace: C5 is refused because its output path is under /home, and C4 is refused for /etc/passwd, so the allowlist plus the path check gives RESTRICTED in either execution mode. Allowlist with validated arguments reaches the same result without the path check by refusing --output and any semicolon. With the denylist, the path check still lets C6 through.

    Why deny lists fail in both directions

    A denylist describes known bad strings. It blocked a harmless file name and missed a harmless-looking flag and an interpreter. With No policy, four harmful commands run through a shell; three still run as an argument vector, because only the injected curl depends on the shell. Decide what may run, with which arguments and where, and treat everything else as refused.

    Reading the run and its limits

    Play, Next event, Restart, Speed and Inspection time step through the policy, each command decision and the outcome across sixty seconds; the table lists every command, its intent and the decision. Nothing is executed: the model matches text exactly as shown. Real shell tools also need an unprivileged user, a scratch file system, resource limits, default-deny network egress and an audit record of every call.