Describe the bug
If I have a hook that keeps agents from doing a dangerous command and then tell Copilot to run the command via a background/task or general-purpose agent, the sub-agent can run the command no problem.
This feels like a security vulnerability: just jailbreak the agent or even have it get frustrated that something doesn't work, and have it spawn a new agent to do the dirty deed for it.
Any preToolUse hook that enforces policy (file permissions, lock checks, security scanning) is bypassed entirely by sub-agents. This applies to all sub-agent types tested: task (Haiku), general-purpose (Sonnet). Both global (~/.copilot/hooks/) and project-level (.github/hooks/) hooks are affected. sessionStart hooks also do not fire for sub-agents.
Affected version
1.0.37
Steps to reproduce the behavior
- Create a global hook that logs all preToolUse invocations:
File: ~/.copilot/hooks/hooks.json
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"powershell": "$i = [Console]::In.ReadToEnd() | ConvertFrom-Json; $ts = Get-Date -Format 'HH:mm:ss'; Add-Content -Path
\"$env:USERPROFILE\\.copilot\\hooks\\hook-test.log\" -Value \"[$ts] preToolUse | tool=$($i.toolName) | sid=$env:COPILOT_SESSION_ID\"",
"timeoutSec": 5
}
]
}
}
- Create a test file:
echo "// original" > test-hook.txt
- Start a new Copilot CLI session (restart if needed to pick up hooks).
- Verify the hook fires for the main session:
- Ask Copilot: Edit test-hook.txt and change the comment to "// main session"
- Check the log:
Get-Content "$env:USERPROFILE\.copilot\hooks\hook-test.log"
- Expected: Log entry showing
preToolUse | tool=edit (main CLI session logs show up).
- Now ask Copilot to dispatch a sub-agent that edits the same file:
- Ask Copilot: Use the task tool to dispatch a sub-agent that edits test-hook.txt and changes the comment to "// sub-agent was here"
- Check the log again:
Get-Content "$env:USERPROFILE\.copilot\hooks\hook-test.log"
- Expected: New log entry showing
preToolUse | tool=edit from the sub-agent's edit call. Actual: ❌ No new entry. Only the parent session's preToolUse | tool=task is logged (for dispatching the task), but the sub-agent's edit call within that task produces no hook invocation.
- Verify the sub-agent's edit went through unguarded:
Get-Content test-hook.txt
- Shows:
// sub-agent was here
Expected behavior
All hook triggers (preToolUse, postToolUse, sessionStart, etc.) should fire for tool calls made by sub-agents (spawned via the task tool) with the same semantics as the parent session. A preToolUse hook that returns {"permissionDecision":"deny"} should block the sub-agent's tool call, not just the parent's.
In my case, only parent session gets any hook controls. Sub-agents are uninhibited and untraceable.
Additional context
- Windows 11
- Windows Terminal
Describe the bug
If I have a hook that keeps agents from doing a dangerous command and then tell Copilot to run the command via a background/task or general-purpose agent, the sub-agent can run the command no problem.
This feels like a security vulnerability: just jailbreak the agent or even have it get frustrated that something doesn't work, and have it spawn a new agent to do the dirty deed for it.
Any
preToolUsehook that enforces policy (file permissions, lock checks, security scanning) is bypassed entirely by sub-agents. This applies to all sub-agent types tested: task (Haiku), general-purpose (Sonnet). Both global (~/.copilot/hooks/) and project-level (.github/hooks/) hooks are affected.sessionStarthooks also do not fire for sub-agents.Affected version
1.0.37
Steps to reproduce the behavior
File: ~/.copilot/hooks/hooks.json
{ "version": 1, "hooks": { "preToolUse": [ { "type": "command", "powershell": "$i = [Console]::In.ReadToEnd() | ConvertFrom-Json; $ts = Get-Date -Format 'HH:mm:ss'; Add-Content -Path \"$env:USERPROFILE\\.copilot\\hooks\\hook-test.log\" -Value \"[$ts] preToolUse | tool=$($i.toolName) | sid=$env:COPILOT_SESSION_ID\"", "timeoutSec": 5 } ] } }Get-Content "$env:USERPROFILE\.copilot\hooks\hook-test.log"preToolUse | tool=edit(main CLI session logs show up).Get-Content "$env:USERPROFILE\.copilot\hooks\hook-test.log"preToolUse | tool=editfrom the sub-agent's edit call. Actual: ❌ No new entry. Only the parent session'spreToolUse | tool=taskis logged (for dispatching the task), but the sub-agent's edit call within that task produces no hook invocation.Get-Content test-hook.txt// sub-agent was hereExpected behavior
All hook triggers (preToolUse, postToolUse, sessionStart, etc.) should fire for tool calls made by sub-agents (spawned via the task tool) with the same semantics as the parent session. A preToolUse hook that returns {"permissionDecision":"deny"} should block the sub-agent's tool call, not just the parent's.
In my case, only parent session gets any hook controls. Sub-agents are uninhibited and untraceable.
Additional context