Skip to content

fix: use ${COPILOT_PLUGIN_ROOT} in hooks.json to fix cwd crash#587

Open
kwacky1 wants to merge 1 commit into
gm3dmo:mainfrom
kwacky1:fix/hooks-cwd-plugin-root
Open

fix: use ${COPILOT_PLUGIN_ROOT} in hooks.json to fix cwd crash#587
kwacky1 wants to merge 1 commit into
gm3dmo:mainfrom
kwacky1:fix/hooks-cwd-plugin-root

Conversation

@kwacky1

@kwacky1 kwacky1 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Problem

preToolUse hooks crash with preToolUse hook errored whenever the session cwd is anywhere other than the plugin directory. This blocks every tool call in sessions launched with --tickets or any other flag that bundles the-power.

Repro (verified 2026-07-05): Launch any Copilot CLI session from an unrelated repo (e.g. si-clops) with the plugin active. Every tool call returns preToolUse hook errored.

Root cause: hooks.json used "cwd": "." (commit 538bcac) then "cwd": "${PLUGIN_ROOT}" (commit 1f7a3d7 — partial fix), plus a relative "bash": "./hooks/guard-*.sh". The runtime resolves . against session cwd, not the plugin dir. With a relative bash path, the script is never found.

# Reproduces the failure:
cd ~/some-project
echo '{"tool_name":"bash","tool_input":{"command":"echo hello"}}' | bash ./hooks/guard-destructive-ops.sh
# bash: ./hooks/guard-destructive-ops.sh: No such file or directory — exit 127

Fix

Move the absolute path into the bash field using ${COPILOT_PLUGIN_ROOT} — the token the Copilot CLI runtime injects for the plugin install directory. Remove the cwd field entirely (no longer needed).

Evidence of runtime support: config_loader_expand_plugin_hook_config, config_loader_expand_plugin_root_in_object, and the literal ${COPILOT_PLUGIN_ROOT} / ${PLUGIN_ROOT} strings are all present in the Copilot CLI runtime.node native module (v1.0.69-1). The si-clops plugin uses the same pattern and works correctly.

{
  "type": "command",
  "bash": "${COPILOT_PLUGIN_ROOT}/hooks/guard-destructive-ops.sh",
  "timeoutSec": 10
}

Changes

  • copilot-plugin/hooks.json — use ${COPILOT_PLUGIN_ROOT}/hooks/... in bash field; remove cwd field
  • copilot-plugin/tests/test-guardrails.sh — run test suite from a temporary directory (not the plugin dir) to catch future regressions; 4 new cwd-independence test cases
  • copilot-plugin/README.md — document the fix and add 'Testing hooks locally' section

Testing

bash copilot-plugin/tests/test-guardrails.sh
# 39 tests: 39 passed, 0 failed

The test suite now cd's to a temp dir before running, so all 39 tests exercise hooks from a foreign cwd.

Related

Fixes #579 (part of the same safety hook neighbourhood)
Related: PR #580 (fail-open behaviour)

preToolUse hooks crashed with 'preToolUse hook errored' whenever the
session cwd was anywhere other than the plugin directory. Root cause:
hooks.json used `cwd: "."` (later partially fixed to `cwd: "${PLUGIN_ROOT}"`
in the previous commit) plus relative paths in the `bash` field. The
runtime resolved `.` against session cwd, so `./hooks/guard-*.sh` was
not found.

Fix: move the absolute path into the `bash` field using
`${COPILOT_PLUGIN_ROOT}` — the token the Copilot CLI runtime injects
for the plugin install directory. Remove the `cwd` field entirely since
it is no longer needed. This matches the pattern used by si-clops and
other plugins that work correctly from any session directory.

Evidence of runtime support: `config_loader_expand_plugin_hook_config`,
`config_loader_expand_plugin_root_in_object`, and the literal
`${COPILOT_PLUGIN_ROOT}`/`${PLUGIN_ROOT}` strings are all present in
the Copilot CLI runtime.node native module (v1.0.69-1).

Test suite updated to run from a temporary cwd (not the plugin dir) to
catch future regressions. README documents the fix and adds a 'Testing
hooks locally' section.

Verified: repro confirmed (exit 127 from wrong cwd with old config);
39/39 tests pass with new config including 4 new cwd-independence tests.

Fixes gm3dmo#579
Related: PR gm3dmo#580 (fail-open behaviour)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

preToolUse guardrail hooks fail-closed on non-bash tools (blocks all MCP calls)

1 participant