Skip to content

Shell-normalizing command policy for gating agent-executed commands #580

Description

@iret77

Origin

Competitive analysis of yc-software/qm (2026-08-01). Relevant to omadia once agents can execute commands (see the durable-sandbox issue) — and already relevant today for write-capable connector tools.

Concept

qm's command policy is not naive regex-on-raw-string. A shell normalizer unwraps quoting layers before rules are applied: "…", '…', $'…' with ANSI-C decoding, backslashes, recursion (depth 8) into $(…), backticks, pipes to sh, here-strings and variable payloads; a small shell tokenizer tracks quote/substitution state, redirects, and command prefixes.

Rules are {pattern, decision: allow | deny | require_approval, reason} with an org floor (recursive rm, git push --force, DROP/TRUNCATE, fork bombs, pipe-to-shell hard-denied); org allowlist beats scope denylist; regexes are compiled through a ReDoS guard. The policy applies in every posture, including dangerous. Their own SECURITY.md is honest that this is "a speed bump against mistakes and injection, not a sandbox boundary" — the right framing.

Why adopt

Whenever omadia gains an execute tool, we will need exactly this, and getting the normalizer right is the hard 80%. The pattern (normalize → tokenize → rule cascade with org floor) is directly liftable; the two-phase-confirmation ADR we already have covers the approval UX side.

Reference (qm source)

  • src/policy/command-policy.ts (~800 LOC: scannableCommand, scanShell, rule composition)
  • src/util/safe-regex.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfrom-qmConcept inspired by yc-software/qm (YC competitive analysis)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions