Skip to content

hardcoded-path-check: no per-file exemption when CLAUDE_PROJECT_DIR is not a git working tree #1094

Description

@kyle-sexton

Parent

Source: handoff-inbox item 20260723-014618-guardrails-hpp-win-repo-pattern-gaps (Finding 2), producer work-laptop (Windows/PowerShell), guardrails 0.12.1. Residual case adjacent to #1038 (fixed by #1039).

What to build

The #1039 fix skips hardcoded-path-check when CLAUDE_PROJECT_DIR is unset. But when the harness resolves a project dir that is NOT a git working tree — home-directory sessions being the common case (per current official hooks docs, CLAUDE_PROJECT_DIR "can be any directory, not just git repositories") — the scope guard passes and the exemption ladder then has no reachable rung:

  • the *.claude/hooks/* and *.claude/projects/* carve-outs do not cover .claude/<plugin>.conf;
  • git -C "$CLAUDE_PROJECT_DIR" check-ignore errors (not a repo), so the gitignore allowlist can never fire;
  • the only remaining escape is the global hardcoded_path_check_enabled=false kill switch.

Reproduced live: a Write of ~/.claude/repo-fleet-hygiene.conf (a machine-local gitconfig-format file whose entire purpose is naming machine paths) was blocked with no per-file exemption path.

Extend the scope guard: skip when CLAUDE_PROJECT_DIR is not a git working tree (git -C "$CLAUDE_PROJECT_DIR" rev-parse --is-inside-work-tree fails). Same rationale as the #1039 fix and the hook's own stated philosophy: hardcoded paths only harm portable repo artifacts; a non-repo project dir means the target is not one, and scanning there leaves no per-file exemption short of the global kill switch. Update the hook's header comment and the README scoping bullet to state the new rung.

Acceptance criteria

  • With CLAUDE_PROJECT_DIR set to a non-repo directory, a write of a file under it (e.g. .claude/some-plugin.conf containing absolute paths) is NOT blocked
  • With CLAUDE_PROJECT_DIR set to a real git working tree, detection behavior is unchanged (existing suite passes)
  • Test added covering the non-repo project-dir skip
  • Hook header comment + guardrails README scoping documentation updated to name the non-repo skip
  • shellcheck clean; guardrails version bump + CHANGELOG entry

Blocked by

None — can start immediately.

Metadata

Metadata

Assignees

Labels

priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions