fix(security): honor shell hook blocks even when message/reason is absent#27231
fix(security): honor shell hook blocks even when message/reason is absent#27231flamiinngo wants to merge 3 commits into
Conversation
This comment was marked as spam.
This comment was marked as spam.
|
Thanks for the thorough review — addressed all points:
|
This comment was marked as spam.
This comment was marked as spam.
|
Updated — isinstance guard restored, _DEFAULT_BLOCK_MESSAGE constant extracted, _block_message() helper added to unify the two branches, and 4 unit tests added covering missing message, missing reason, empty string, and non-string type. All 14 TestParseResponse tests pass. |
4f17e21 to
a2d5193
Compare
This comment was marked as spam.
This comment was marked as spam.
…sent
_parse_response in agent/shell_hooks.py only forwarded a pre_tool_call
block directive if the hook also provided a non-empty message or reason.
When either field was missing the function returned None, causing Hermes
to treat the response as a no-op and execute the tool unconditionally.
This means a hook that outputs {"action": "block"} or {"decision": "block"}
without a reason string is silently ignored. The security boundary fails
open: tools the user intended to gate are executed anyway.
Fix: remove the message-presence guard. Honor the block unconditionally
and fall back to a default message when none is provided. Existing hooks
that already include a message or reason are unaffected.
… block handler Address code review feedback on _parse_response: 1. Restore isinstance(raw, str) guard so non-string message/reason values (e.g. integers, lists) from a malformed hook response fall back to the default rather than being forwarded as-is. This keeps the contract that message in the returned dict is always a string. 2. Extract the repeated literal 'Blocked by shell hook.' into a module-level constant _DEFAULT_BLOCK_MESSAGE to avoid duplication and make it easy to change in one place. Four new unit tests added to tests/agent/test_shell_hooks.py covering: - action block with no message (uses default) - decision block with no reason (uses default) - action block with empty string message (uses default) - action block with non-string message, e.g. integer (uses default)
…c in _parse_response Both the `action=block` and `decision=block` branches in _parse_response shared identical field-priority and type-validation logic. Extract it into a single _block_message(primary, secondary) helper so the two branches are one line each and the type guard lives in exactly one place. No functional change: existing tests (TestParseResponse, 14 tests) all pass unchanged, confirming identical behaviour.
a2d5193 to
12ec5d5
Compare
…tors Adds release-note attribution mappings for the contributors from group 5: - @haran2001 (PR #27070, #27068) - @ms-alan (PR #26443) - @godlin-gh (PR #26118) - @wesleysimplicio (PR #25777, ext-email form) - @Carry00 (PR #26851) - @alaamohanad169-ship-it (PR #26036) - @hawknewton (PR #26294) (YanzhongSu PR #25879 and flamiinngo PR #27231 already mapped.)
|
Merged via PR #27382 — your commit was cherry-picked onto current |
…tors Adds release-note attribution mappings for the contributors from group 5: - @haran2001 (PR NousResearch#27070, NousResearch#27068) - @ms-alan (PR NousResearch#26443) - @godlin-gh (PR NousResearch#26118) - @wesleysimplicio (PR NousResearch#25777, ext-email form) - @Carry00 (PR NousResearch#26851) - @alaamohanad169-ship-it (PR NousResearch#26036) - @hawknewton (PR NousResearch#26294) (YanzhongSu PR NousResearch#25879 and flamiinngo PR NousResearch#27231 already mapped.)
Bug
_parse_responseinagent/shell_hooks.pyonly forwarded apre_tool_callblock directive if the hook also provided a non-emptymessageorreason. When either field was missing the functionreturned
None, causing Hermes to treat the block as a no-op andexecute the tool unconditionally.
A hook that outputs
{"action": "block"}or{"decision": "block"}without a reason string is silently ignored. The security boundary
fails open — tools the user intended to gate are executed anyway.
Reproduction