Skip to content

chore(hooks): guard-git.sh's commit edit-log check has the same unresolved-cwd gap as #2386's branch validation #2526

Description

@carlos-alm

Summary

Split out from #2386 while fixing that issue's branch-validation bug — a related but distinct gap in the same file.

guard-git.sh's commit-validation section (the block starting if echo "$NCOMMAND" | grep -qE '...git[[:space:]]+commit') resolves its target directory via WORK_DIR=$(detect_work_dir commit), then falls back to the hook's own ambient cwd when WORK_DIR is empty:

else
  PROJECT_DIR=$(git rev-parse --show-toplevel 2>/dev/null) || PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
  STAGED_FILES=$(git diff --cached --name-only 2>/dev/null) || true
  ...

This is the same root cause #2386 fixed for validate_branch_name: a bare git commit <files> -m "msg" relying on the Bash tool's persistent cwd from an earlier, separate tool call (rather than an explicit git -C <dir> commit or cd <dir> && git commit) leaves WORK_DIR empty, and the fallback resolves against the wrong repo.

Why this is lower severity than #2386 (and worth a separate issue)

Unlike the branch-validation case, this doesn't currently produce a false deny: if the wrong repo's git diff --cached --name-only comes back empty (likely, since nothing is staged in the unrelated repo), the check hits its existing if [ -z "$STAGED_FILES" ]; then exit 0 early-out and silently allows. So the observable symptom today is "the edit-log check gets silently skipped" rather than "a valid commit gets wrongly blocked" — milder, but still means the edit-log protection this check exists to provide (catching another session's files sneaking into your commit) doesn't actually run when it should.

Suggested fix

Apply the same $HOOK_CWD fallback #2386 introduces for validate_branch_name to this section too — guard-git.sh already extracts HOOK_CWD from the hook's top-level cwd JSON field as of that fix; reuse it here:

WORK_DIR=$(detect_work_dir commit)
if [ -z "$WORK_DIR" ] && [ -n "$HOOK_CWD" ] && [ -d "$HOOK_CWD" ]; then
  WORK_DIR="$HOOK_CWD"
fi

Remember to keep .claude/hooks/guard-git.sh and docs/examples/claude-code-hooks/guard-git.sh byte-identical (enforced by tests/unit/hook-guard-git-clean.test.ts).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions