From dce36cc9ddc614bd406cf79cadee4799563ccbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Sun, 19 Jul 2026 05:11:30 -0400 Subject: [PATCH] fix: harden Python hook command detection --- sdks/python/elydora/plugins/claudecode.py | 14 +++++------ sdks/python/elydora/plugins/gemini.py | 14 +++++------ sdks/python/elydora/plugins/letta.py | 14 +++++------ .../tests/test_settings_hook_detection.py | 23 +++++++++++++++++++ 4 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 sdks/python/tests/test_settings_hook_detection.py diff --git a/sdks/python/elydora/plugins/claudecode.py b/sdks/python/elydora/plugins/claudecode.py index 67bf466..f272031 100644 --- a/sdks/python/elydora/plugins/claudecode.py +++ b/sdks/python/elydora/plugins/claudecode.py @@ -174,16 +174,16 @@ class ClaudeCodePlugin(AgentPlugin): def _is_elydora_hook(entry: dict, agent_id: str = "") -> bool: # Collect all command strings from the entry - commands = [] + commands: list[str] = [] inner_hooks = entry.get("hooks") if isinstance(inner_hooks, list): - commands.extend( - h.get("command", "") - for h in inner_hooks - if isinstance(h, dict) - ) + for hook in inner_hooks: + if isinstance(hook, dict) and isinstance(hook.get("command"), str): + commands.append(hook["command"]) else: - commands.append(entry.get("command", "")) + command = entry.get("command") + if isinstance(command, str): + commands.append(command) for cmd in commands: cmd_lower = cmd.lower() diff --git a/sdks/python/elydora/plugins/gemini.py b/sdks/python/elydora/plugins/gemini.py index ce8471f..11156cf 100644 --- a/sdks/python/elydora/plugins/gemini.py +++ b/sdks/python/elydora/plugins/gemini.py @@ -170,16 +170,16 @@ class GeminiPlugin(AgentPlugin): def _is_elydora_hook(entry: dict, agent_id: str = "") -> bool: # Collect all command strings from the entry - commands = [] + commands: list[str] = [] inner_hooks = entry.get("hooks") if isinstance(inner_hooks, list): - commands.extend( - h.get("command", "") - for h in inner_hooks - if isinstance(h, dict) - ) + for hook in inner_hooks: + if isinstance(hook, dict) and isinstance(hook.get("command"), str): + commands.append(hook["command"]) else: - commands.append(entry.get("command", "")) + command = entry.get("command") + if isinstance(command, str): + commands.append(command) for cmd in commands: cmd_lower = cmd.lower() diff --git a/sdks/python/elydora/plugins/letta.py b/sdks/python/elydora/plugins/letta.py index fc4e9a0..ad262c4 100644 --- a/sdks/python/elydora/plugins/letta.py +++ b/sdks/python/elydora/plugins/letta.py @@ -172,16 +172,16 @@ class LettaPlugin(AgentPlugin): def _is_elydora_hook(entry: dict, agent_id: str = "") -> bool: # Collect all command strings from the entry - commands = [] + commands: list[str] = [] inner_hooks = entry.get("hooks") if isinstance(inner_hooks, list): - commands.extend( - h.get("command", "") - for h in inner_hooks - if isinstance(h, dict) - ) + for hook in inner_hooks: + if isinstance(hook, dict) and isinstance(hook.get("command"), str): + commands.append(hook["command"]) else: - commands.append(entry.get("command", "")) + command = entry.get("command") + if isinstance(command, str): + commands.append(command) for cmd in commands: cmd_lower = cmd.lower() diff --git a/sdks/python/tests/test_settings_hook_detection.py b/sdks/python/tests/test_settings_hook_detection.py new file mode 100644 index 0000000..e790ac6 --- /dev/null +++ b/sdks/python/tests/test_settings_hook_detection.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +from collections.abc import Callable + +import pytest + +from elydora.plugins.claudecode import _is_elydora_hook as is_claude_hook +from elydora.plugins.gemini import _is_elydora_hook as is_gemini_hook +from elydora.plugins.letta import _is_elydora_hook as is_letta_hook + + +HookDetector = Callable[[dict, str], bool] + + +@pytest.mark.parametrize("detector", [is_claude_hook, is_gemini_hook, is_letta_hook]) +def test_hook_detection_handles_only_string_commands(detector: HookDetector) -> None: + assert detector({"command": 42}, "") is False + assert detector({"hooks": [{"command": None}]}, "") is False + assert detector({"hooks": [{"command": "run .elydora/agent-1/hook.py"}]}, "") is True + assert detector( + {"hooks": [{"command": "run .elydora/agent-1/hook.py"}]}, + "agent-2", + ) is False