Skip to content

Fail closed when the pre-bash guard cannot parse the payload#35

Merged
cgraf78 merged 1 commit into
mainfrom
fix-fail-closed-parse
Jul 1, 2026
Merged

Fail closed when the pre-bash guard cannot parse the payload#35
cgraf78 merged 1 commit into
mainfrom
fix-fail-closed-parse

Conversation

@cgraf78

@cgraf78 cgraf78 commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

Make _hook_parse_command refuse to run a command it cannot inspect,
instead of silently allowing it.

Previously, after reading a payload, an empty extracted command exited 0
(allow) — so a missing/broken jq or malformed JSON disabled the entire
bash guard: the agent harness parses the payload with its own reader and
still runs .tool_input.command, so the command executed uninspected. A
single missing jq on PATH silently turned the guard off.

  • for a PRE-execution hook (pre-bash), a present-but-unparsable payload
    now fails CLOSED: jq missing, or jq empty failing (broken jq /
    malformed JSON), blocks with an actionable message. _hook_finish for
    this no-context hook emits {} + exit 2 without needing jq, so the
    block works even when jq is what's missing — for both Claude and Codex
  • genuinely empty stdin (no tool call) still exits 0 (no-op), and valid
    JSON with no command field still allows (nothing to run; the harness
    sees the same empty command)
  • PostToolUse (post-bash) keeps its advisory no-op on parse failure — it
    can't prevent an already-run command, so it must not emit a block
  • suppress the raw jq error on the command-extraction line for
    valid-but-non-object JSON

Testing

  • new agent-hook-bash-parse-test: 21 assertions — pre-bash blocks on
    malformed JSON and missing jq (Claude and Codex), allows empty stdin /
    no-command / non-object JSON without stderr noise, and post-bash stays
    a no-op on parse failure
  • full suite: 1040 passed, 0 failed; checkrun lint + shellcheck -x clean

Reviewed by an adversarial fresh-eyes pass (fail-closed correctness for
both agents incl. missing-jq, no new bypass, no over-blocking); its three
low-severity findings — post-bash no-op, no stderr noise, Codex coverage —
are all folded into this change.

Summary
make `_hook_parse_command` refuse to run a command it cannot inspect,
instead of silently allowing it.

Previously, after reading a payload, an empty extracted command exited 0
(allow) — so a missing/broken `jq` or malformed JSON disabled the entire
bash guard: the agent harness parses the payload with its own reader and
still runs `.tool_input.command`, so the command executed uninspected. A
single missing `jq` on PATH silently turned the guard off.

- for a PRE-execution hook (pre-bash), a present-but-unparsable payload
  now fails CLOSED: `jq` missing, or `jq empty` failing (broken jq /
  malformed JSON), blocks with an actionable message. `_hook_finish` for
  this no-context hook emits `{}` + exit 2 without needing jq, so the
  block works even when jq is what's missing — for both Claude and Codex
- genuinely empty stdin (no tool call) still exits 0 (no-op), and valid
  JSON with no command field still allows (nothing to run; the harness
  sees the same empty command)
- PostToolUse (post-bash) keeps its advisory no-op on parse failure — it
  can't prevent an already-run command, so it must not emit a block
- suppress the raw jq error on the command-extraction line for
  valid-but-non-object JSON

Testing
- new agent-hook-bash-parse-test: 21 assertions — pre-bash blocks on
  malformed JSON and missing jq (Claude and Codex), allows empty stdin /
  no-command / non-object JSON without stderr noise, and post-bash stays
  a no-op on parse failure
- full suite: 1040 passed, 0 failed; checkrun lint + shellcheck -x clean
@cgraf78 cgraf78 merged commit 3894a10 into main Jul 1, 2026
6 checks passed
@cgraf78 cgraf78 deleted the fix-fail-closed-parse branch July 1, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant