Description
When a hook is installed, buildHookScript() is given a concrete cliPath for the installed CLI. However, the generated hook prefers any commit-echo executable found on PATH and only falls back to the saved cliPath when that command is absent.
This means the hook is not actually pinned to the version/path that was installed. Changes to PATH can silently switch the implementation that runs during every commit.
Location
src/git/hook.ts:85-95 — buildHookScript()
Relevant code
if command -v commit-echo >/dev/null 2>&1; then
commit-echo hook 'prepare-commit-msg' "$@"
elif [ -f '/path/to/installed/dist/index.js' ]; then
node '/path/to/installed/dist/index.js' hook 'prepare-commit-msg' "$@"
fi
Steps to reproduce
- Install a hook while
cliPath points to one commit-echo installation.
- Later put a different
commit-echo executable earlier on PATH (for example a different global version or an unrelated wrapper).
- Run a Git commit.
- The hook invokes the PATH-resolved binary instead of the saved
cliPath.
Expected behavior
A managed hook should run the exact CLI installation selected at hook installation time, or provide an explicit documented mechanism for opting into PATH-based resolution.
Actual behavior
PATH takes precedence over the saved CLI path, so hook behavior can change without reinstalling the hook.
Suggested fix
Prefer the saved absolute cliPath in the generated script and only fall back to PATH when the saved installation is unavailable. Consider recording the resolved executable explicitly when installing.
Impact
Version drift can break hook compatibility unexpectedly, and environments with a conflicting commit-echo executable can run unintended code during every commit. The issue is particularly surprising because the hook installer already computes and stores a concrete CLI path.
Reviewed against current main at c67ff967a018d5fd4b032f6ef6a4981ac9d76a12.
Description
When a hook is installed,
buildHookScript()is given a concretecliPathfor the installed CLI. However, the generated hook prefers anycommit-echoexecutable found onPATHand only falls back to the savedcliPathwhen that command is absent.This means the hook is not actually pinned to the version/path that was installed. Changes to
PATHcan silently switch the implementation that runs during every commit.Location
src/git/hook.ts:85-95—buildHookScript()Relevant code
Steps to reproduce
cliPathpoints to one commit-echo installation.commit-echoexecutable earlier onPATH(for example a different global version or an unrelated wrapper).cliPath.Expected behavior
A managed hook should run the exact CLI installation selected at hook installation time, or provide an explicit documented mechanism for opting into PATH-based resolution.
Actual behavior
PATH takes precedence over the saved CLI path, so hook behavior can change without reinstalling the hook.
Suggested fix
Prefer the saved absolute
cliPathin the generated script and only fall back to PATH when the saved installation is unavailable. Consider recording the resolved executable explicitly when installing.Impact
Version drift can break hook compatibility unexpectedly, and environments with a conflicting
commit-echoexecutable can run unintended code during every commit. The issue is particularly surprising because the hook installer already computes and stores a concrete CLI path.Reviewed against current
mainatc67ff967a018d5fd4b032f6ef6a4981ac9d76a12.