github / github/copilot-cli

preToolUse hooks silently bypassed under parallel tool calls (timeout->allow fallback + serial dispatch)

Đang mở
#2,893 2 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:permissions area:plugins
Ngôn ngữ chính
Shell
Star
11.2k
Fork
1.9k
Merge trung bình
14 giờ 16 phút
Pull request đã merge (30 ngày)
6

Mô tả

## Describe the bug

`preToolUse` hooks are silently bypassed under parallel tool calls because:

1. **`timeoutSec` does not terminate the hook process** — when a hook takes longer than `timeoutSec`, the CLI stops waiting but the hook subprocess keeps running. The CLI then proceeds with an **implicit allow** (fail-open). Any `permissionDecision: deny` that the hook eventually writes to stdout is discarded.
2. **Hook invocations are serialized** — when several tools are invoked in parallel (e.g. from the agent), `preToolUse` hooks are dispatched one-by-one with ~1.5–4 s gaps, even though the tool calls themselves land within a <100 ms window. Combined with (1), the later items in the queue are the ones most likely to exceed `timeoutSec` and get fail-open'd.

The net effect is that a security-oriented hook (e.g. a local guard that blocks dangerous commands) becomes probabilistically unreliable as soon as the agent fires more than a handful of tools concurrently. The reported "hook race condition" turns out not to be a race inside the hook, but a silent allow-fallback on timeout.

## Affected version

```
1.0.35-2 (Windows_NT)
```

Likely affects other recent versions; not tested across matrix.

## Steps to reproduce the behavior

Minimal reproducer using a Python 3 hook. Save as `slow-deny.py`:

```python
import json, sys, time
sys.stdin.read()
time.sleep(15) # longer than timeoutSec
print(json.dumps({"permissionDecision": "deny", "permissionDecisionReason": "should block"}))
```

And `~/.copilot/hooks/hooks.json`:

```json
{
"version": 1,
"hooks": {
"preToolUse": [
{
"type": "command",
"bash": "python3 \"$HOME/slow-deny.py\"",
"powershell": "py -3 \"$HOME\\slow-deny.py\"",
"timeoutSec": 10
}
]
}
}
```

Start `copilot` and ask the agent to run any shell command (e.g. `echo hi`).

**Expected**: the command is blocked (the hook wrote `deny`, even if late).
**Actual**: the command executes. The hook logs `permissionDecision: deny` after the CLI has already moved on.

A second reproducer shows the serialization behavior: ask the agent to run ~5 shell commands in the same turn. Logging the hook's start time (`datetime.now()`) shows the hooks firing at +0 s, +1.5 s, +4.6 s, +7.1 s, +11.1 s despite the tool calls all starting within ~100 ms.

## Expected behavior

At least one of:

- `timeoutSec` should kill the hook process (so subsequent failure modes are visible), **and** a timed-out hook should fall back to `deny` (fail-closed) — not to an implicit `allow`.
- Provide an explicit configuration knob (e.g. `onTimeout: "deny" | "allow"`) so operators can opt into fail-closed semantics.
- Document the current behavior clearly; right now the docs describe `timeoutSec` without specifying the fallback direction.

Ideally also: dispatch `preToolUse` hooks in parallel rather than serializing them, since each tool call is independent.

## Additional context

- OS: Windows 11, `powershell` invocation path
- Reproduced with minimal `py -3` hook (no `uv`, no third-party dependencies), so the latency is CLI-side scheduling rather than hook startup cost
- Observations:
- `dur_stdout_written - dur_invoked` for the slow hook is ~15 s (full sleep), confirming the process is not killed at the 10 s timeout
- For 5 parallel tool invocations, hook start times were spaced 1.5–4 s apart — consistent with a serial queue on the CLI side
- The bypass probability grows with parallelism, matching community reports of "preToolUse race condition under high concurrency"
- Security impact: any user who relies on `preToolUse` hooks for safety (e.g. blocking writes to sensitive paths, blocking dangerous URLs) silently loses that protection under high concurrency

Happy to share a full minimal repro repo or detailed logs on request.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.