Omnigent agent-harness guardrail fails open on unrecognized shell commands, letting confined agents push to arbitrary repos
Undisclosed·Omnigent (meta-harness running Claude Code / Codex / Pi with policy-based guardrails and sandboxing)Fixed
Omnigent's shared shell-command parser (policies/builtins/_shell.py) returned None for any gated command it didn't recognize, and the policy evaluator treated that None/abstain result as ALLOW; commands wrapped in bash -lc, timeout/nice/setsid/stdbuf, command substitution ($(...)), or unsplit background operators (&) therefore bypassed both the GitHub repo/branch allowlist and the working-directory confinement, letting a confined or prompt-injected agent git push to an attacker-controlled repo or protected branch, or escape its workspace via git worktree add / git -C.
- Blast radius
- No real-world exploitation or victim organisation disclosed; impact is the demonstrated bypass class itself — an agent believed to be confined to an allowlisted repo/branch and working directory could instead exfiltrate code/secrets to an outside repo or break out of its sandboxed workspace on any deployment running omnigent < 0.3.0.
- Root cause
- The security gate's command parser had an incomplete list of disallowed inputs (CWE-184) and, on failing to classify a gated command, resolved the ambiguous/abstain case to allow instead of deny, so unrecognized wrapper syntax, substitution, and control operators silently skipped the allowlist and workspace-confinement checks.
- How it was caught
- Found and reported by an autonomous security research agent (Aaron/Aeon) that probed the policy code and verified specific bypass strings (bash -lc, timeout/nice/setsid/stdbuf wrappers, command substitution, unsplit '&'), rather than through production monitoring or an actual attack.
- What changed
- Maintainers patched in omnigent 0.3.0 (PR #389, commit 1a05b7b): unrecognized gated commands now DENY instead of defaulting to allow, known wrappers (timeout/nice/setsid/stdbuf/env) are canonicalized to their inner command before evaluation, and shell payloads/substitutions are recursed into and split on control operators (; & && || |) before each segment is judged.
Take-awaySecurity-gate parsers must fail closed: any command the parser cannot classify should be denied, not treated as an abstain that resolves to allow.