Commands
NAME
MCP::Client::Policy::Commands - what a shell tool call would actually run
DESCRIPTION
A shell tool takes an argv vector and execs it directly ā no shell ā so a
rule that matches command => 'git' can trust that the program really is
git. The one hole is a model that runs the shell itself:
< ['bash', '-c', 'git status && rm -rf /'] > is a single bash to the
argv, but two commands to the machine, and the second is not git.
This module closes that hole. Given the literal argv of a call it returns the
list of commands the call effectively runs: it strips fixed wrappers
(env, timeout, nice ā¦), and when the program is a shell run with
-c it lexes the payload ā respecting quotes, operators, redirections,
command substitutions and parameter expansion ā and returns each simple command
inside it, recursing through nested shells and substitutions.
It never executes anything and never resolves an expansion. Its whole job is to
be safe: everything it cannot read for certain ā a $VAR, a $(ā¦), a
glob, an unbalanced quote ā is reported as unreadable rather than guessed, so a
rule that would allow on a guess never fires and a rule that would deny on doubt
always does. Stripping a wrapper can only ever expose the real program or
mis-name it (which falls through to ask); it can never hide a dangerous one.
The shape it returns
Each effective command is a hash, the same shape evaluate matches against:
programā the normalised program basename, or theStrtype object when the program cannot be identified (an expansion or glob in argv[0]).tokensā the literal argv tokens the engine can read, in order, up to the first one it cannot.sealedā whethertokensis the whole argv tail (True) or stops at an unreadable token (False). Anargsprefix that would read past an unsealed tail isunknown, not a miss.redirect-targetsā the literal targets of any redirections in the command (> file), for rules about what a command may write to.