mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
fix(security): honor shell hook blocks even when message/reason is absent
_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.
This commit is contained in:
parent
8e3cfdfb61
commit
aeda146112
1 changed files with 4 additions and 6 deletions
|
|
@ -515,13 +515,11 @@ def _parse_response(event: str, stdout: str) -> Optional[Dict[str, Any]]:
|
|||
|
||||
if event == "pre_tool_call":
|
||||
if data.get("action") == "block":
|
||||
message = data.get("message") or data.get("reason") or ""
|
||||
if isinstance(message, str) and message:
|
||||
return {"action": "block", "message": message}
|
||||
message = data.get("message") or data.get("reason") or "Blocked by shell hook."
|
||||
return {"action": "block", "message": message}
|
||||
if data.get("decision") == "block":
|
||||
message = data.get("reason") or data.get("message") or ""
|
||||
if isinstance(message, str) and message:
|
||||
return {"action": "block", "message": message}
|
||||
message = data.get("reason") or data.get("message") or "Blocked by shell hook."
|
||||
return {"action": "block", "message": message}
|
||||
return None
|
||||
|
||||
context = data.get("context")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue