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
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 tosh, 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 (recursiverm,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, includingdangerous. 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
executetool, 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