github / github/copilot-cli

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

Offen
#2,893 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area:permissions area:plugins
Vorherrschende Sprache
Shell
Sterne
11.2k
Forks
1.9k
Ø Merge
14 Std. 16 Min.
Gemergte PRs (30 T.)
6

Beschreibung

## 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.

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.