Skip to content

[Reliability] Managed hooks can execute a different commit-echo binary from the installed CLI #308

Description

@404-Page-Found

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

  1. Install a hook while cliPath points to one commit-echo installation.
  2. Later put a different commit-echo executable earlier on PATH (for example a different global version or an unrelated wrapper).
  3. Run a Git commit.
  4. 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.

Activity

  1. 404-Page-Found commented on Sep 20, 2026

    @404-Page-Found
    ContributorAuthor

    Triage

    Priority: P2 — managed-hook reliability / environment safety

    The bug is environment-dependent, but it means a managed hook can silently switch to a different installed binary after PATH changes. That can cause version drift or invoke an unintended wrapper during Git commits.

    Disposition: Fix before treating managed hooks as pinned integrations. This is separate from #278: #278 is about installing an unexpected second hook; #308 is about which executable an installed hook actually invokes.

    Suggested implementation: prefer the captured absolute CLI path and only use PATH as an explicit fallback when the stored installation is unavailable. Add a regression test with two different commit-echo executables on PATH.

  2. added this to the v0.4.0 milestone on Sep 20, 2026
  3. 404-Page-Found commented on Sep 24, 2026

    @404-Page-Found
    ContributorAuthor

    Triage update

    Disposition: Valid bug — P2, managed-hook reliability / environment safety.

    Confirmed against current main: buildHookScript() embeds the concrete cliPath, but the generated hook first runs command -v commit-echo. A later PATH change can therefore cause an installed hook to invoke a different commit-echo executable without reinstalling the hook.

    This is consistent with the repository's existing approach in #254, where bare executable resolution was removed to avoid PATH substitution.

    Recommended fix: make the captured CLI path authoritative in the generated hook and use PATH resolution only as an explicit fallback when that installation is unavailable. Add a regression test with two different commit-echo executables on PATH and assert that the saved installation is used.

    This is separate from #278: #278 concerns which hooks are installed; #308 concerns which executable an installed hook invokes.

  4. 404-Page-Found commented on Sep 24, 2026

    @404-Page-Found
    ContributorAuthor

    Implemented in PR #332: #332

    Managed hooks now run the captured cliPath first and only fall back to PATH-based commit-echo resolution when that installation is unavailable. Added a regression test covering both precedence and fallback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingp2Medium priority; affects normal use

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions