Skip to content

Commit 4b5a0b8

Browse files
authored
fix: reject string-like shell commands (#3092)
1 parent 9d24382 commit 4b5a0b8

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

src/agents/run_internal/tool_execution.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,8 +619,12 @@ def coerce_shell_call(tool_call: Any) -> ShellCallData:
619619
raise ModelBehaviorError("Shell call is missing an action payload.")
620620

621621
commands_value = get_mapping_or_attr(action_payload, "commands")
622-
if not isinstance(commands_value, Sequence):
623-
raise ModelBehaviorError("Shell call action is missing commands.")
622+
if isinstance(commands_value, str | bytes | bytearray) or not isinstance(
623+
commands_value, Sequence
624+
):
625+
raise ModelBehaviorError(
626+
"Shell call action commands must be a sequence of command strings."
627+
)
624628
commands: list[str] = []
625629
for entry in commands_value:
626630
if entry is None:

tests/test_shell_call_serialization.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ def test_coerce_shell_call_requires_commands() -> None:
2929
run_loop.coerce_shell_call(tool_call)
3030

3131

32+
@pytest.mark.parametrize("commands", ["echo hi", b"echo hi", bytearray(b"echo hi")])
33+
def test_coerce_shell_call_rejects_string_like_commands(commands: object) -> None:
34+
tool_call = {"call_id": "shell-3", "action": {"commands": commands}}
35+
with pytest.raises(
36+
ModelBehaviorError,
37+
match="Shell call action commands must be a sequence of command strings.",
38+
):
39+
run_loop.coerce_shell_call(tool_call)
40+
41+
3242
def test_normalize_shell_output_handles_timeout() -> None:
3343
entry = {
3444
"stdout": "",

0 commit comments

Comments
 (0)