fix(copilot): address review round 2 — transcript path max_len, subagent tests

- SubagentStop: use max_len=500 for transcript path (consistent with
  pre_compact_hook)
- Add test coverage for SubagentStart/SubagentStop hooks including
  control character sanitization
This commit is contained in:
Zamil Majdy
2026-04-01 17:08:01 +02:00
parent 403a36a3fc
commit ce1555c07a
2 changed files with 72 additions and 1 deletions

View File

@@ -358,7 +358,9 @@ def create_security_hooks(
_ = context, tool_use_id
agent_id = _sanitize(str(input_data.get("agent_id", "?")))
agent_type = _sanitize(str(input_data.get("agent_type", "?")))
transcript = _sanitize(str(input_data.get("agent_transcript_path", "")))
transcript = _sanitize(
str(input_data.get("agent_transcript_path", "")), max_len=500
)
logger.info(
"[SDK] SubagentStop: agent_id=%s, type=%s, user=%s, transcript=%s",
agent_id,

View File

@@ -535,3 +535,72 @@ async def test_mixed_task_agent_share_slots(_hooks):
context={},
)
assert not _is_denied(result)
# ---------------------------------------------------------------------------
# SubagentStart / SubagentStop hooks
# ---------------------------------------------------------------------------
@pytest.fixture()
def _subagent_hooks():
"""Create hooks and return (subagent_start, subagent_stop) handlers."""
hooks = create_security_hooks(user_id="u1", sdk_cwd=SDK_CWD, max_subtasks=2)
start = hooks["SubagentStart"][0].hooks[0]
stop = hooks["SubagentStop"][0].hooks[0]
return start, stop
@pytest.mark.skipif(not _sdk_available(), reason="claude_agent_sdk not installed")
@pytest.mark.asyncio
async def test_subagent_start_hook_returns_empty(_subagent_hooks):
"""SubagentStart hook should return an empty dict (logging only)."""
start, _ = _subagent_hooks
result = await start(
{"agent_id": "sa-123", "agent_type": "research"},
tool_use_id=None,
context={},
)
assert result == {}
@pytest.mark.skipif(not _sdk_available(), reason="claude_agent_sdk not installed")
@pytest.mark.asyncio
async def test_subagent_stop_hook_returns_empty(_subagent_hooks):
"""SubagentStop hook should return an empty dict (logging only)."""
_, stop = _subagent_hooks
result = await stop(
{
"agent_id": "sa-123",
"agent_type": "research",
"agent_transcript_path": "/tmp/transcript.txt",
},
tool_use_id=None,
context={},
)
assert result == {}
@pytest.mark.skipif(not _sdk_available(), reason="claude_agent_sdk not installed")
@pytest.mark.asyncio
async def test_subagent_hooks_sanitize_inputs(_subagent_hooks):
"""SubagentStart/Stop should sanitize control chars from inputs."""
start, stop = _subagent_hooks
# Inject control characters — hook should not raise
result = await start(
{"agent_id": "sa\n-injected\r\x00", "agent_type": "type\ttab"},
tool_use_id=None,
context={},
)
assert result == {}
result = await stop(
{
"agent_id": "sa\n-injected",
"agent_type": "type\r",
"agent_transcript_path": "/tmp/\x00malicious\npath",
},
tool_use_id=None,
context={},
)
assert result == {}