fix(gate): Monitor is a shell — govern it (v0.448.1) - #834
Merged
Merged
Conversation
claude-code's Monitor tool runs an arbitrary shell command and was in neither the hook's routing table nor the PreToolUse matcher, so every call bypassed policy, approval and audit. Route it to shell.exec, refuse the ws form, and add gate-tool-coverage-test to pin matcher/table agreement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vikasprogrammer
force-pushed
the
feat/monitor-gate
branch
from
September 18, 2026 05:23
9190266 to
ba81999
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The hole. claude-code's
Monitortool takes an arbitrary shellcommandand streams its stdout as events. It was missing fromgate-hook.sh's routing table AND from the PreToolUse matcher inclaude-launch.sh, so it never reached the hook at all: no policy classification, no approval, no audit event, no host-egress governance.Live evidence (recent transcripts, instapods + expresstech): ~30
Monitorcalls includinguntil ssh -o BatchMode=yes -i ~/.ssh/<key> root@<host> 'grep -q …',cat > /tmp/watch-multi.sh <<EOF, and token-minting scripts. Same class as the cross-session-messaging channel documented in CLAUDE.md.The fix
Monitoradded to the matcher and routed toshell.exec. Itstool_input.commandhas the same shape as Bash's, soenrichArgscomputes identical facts with no server-side change.wsform (WebSocket, no command) is refused at the hook rather than sent on as a factlessshell.execthat would read as allowed.The test (
scripts/gate-tool-coverage-test.cjs, new, wired intotest:governance) drives the REAL hook as a subprocess against a stub gate: asserts every routed tool is reachable by the matcher, that Monitor arrives asshell.execwith its command text intact, and thatwsis denied. Verified it fails on the pre-fix tree.Note for reviewers: Monitor commands are now gated like Bash, so a risky one (ssh, destructive flags) can pause for approval where it previously ran silently.
🤖 Generated with Claude Code