Repository navigation
Check the Shared Hook Before Installing and Deny a Commit-Time hooksPath Override - #2178
Conversation
…ath Override repo-worktree's hook step told a session to run `pre-commit install` from a new worktree's root. With no core.hooksPath set, a linked worktree's hooks path is the base clone's shared directory, so that install rewrites the hook for every checkout. The step now checks the resolved hooks path first, never installs or switches a shared hook from a linked worktree, and names a commit-time core.hooksPath override as a hook bypass. gh-write-guard now denies `-c core.hooksPath=` and `--config-env` naming that key on a commit or push, beside --no-verify. Fixes #1816 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…e Clones The local review found the new rule contradicting the unchanged Husky.Net bullet, which writes core.hooksPath into the shared config, and stranding a standalone clone with no way to install its own hook. The rule now keys on a linked worktree (git-dir differs from git-common-dir), lets a standalone clone install locally, runs the Husky.Net install only where the setting already reads .husky, drops --path-format for older git, and binds a repository override too. The guard docs name the -c and --config-env forms rather than every per-invocation override. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…Root The second local pass found the rule forbidding the Husky.Net step it sits under, which rewrites core.hooksPath to the value it already holds, and a subdirectory run reading a primary checkout as linked. The rule now forbids changing a shared hook or setting, and runs its git-dir test from the worktree root. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The third local pass found that the .husky precondition left a standalone clone, whose config is its own, with no instruction to install at all, where the old unconditional step covered it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Repository: ptr727/ProjectTemplate/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #2178 +/- ##
========================================
Coverage 56.47% 56.47%
========================================
Files 16 16
Lines 7455 7455
========================================
Hits 4210 4210
Misses 3245 3245
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It changes a security bypass-prevention gate and fleet-wide carried governance content, which the repository treats as design-level and durable-when-wrong, so it warrants final human sign-off despite passing all verification.
Review effort: Balanced
Findings: None
What changed in this PR
This PR closes a hook-safety gap surfaced by the linked issue: running a hook installer (pre-commit/prek/Husky.Net) from a linked worktree rewrote the hook that every checkout of the base clone shares, and a commit-time core.hooksPath override could silently skip hooks the way --no-verify does. It hardens the repo-worktree skill guidance and extends the gh-write-guard PreToolUse hook to deny the per-invocation core.hooksPath override, fitting into the fleet's agent-safety guardrail layer.
Changes:
repo-worktree"Preparing Git Hooks" now checks for an existing shared hook before installing, distinguishes linked worktrees (--git-dirvs--git-common-dir) from standalone clones, forbids changing a shared hook/setting from a linked worktree, and names a commit-timecore.hooksPathoverride as a bypass.gh-write-guard.pydeniesgit -c core.hooksPath=... commit|pushand both--config-envforms, via a new_overrides_hooks_pathhelper and a_git_subcommand_invocationsrefactor that preserves_git_subcommand_arglists; eight self-test rows cover the new positive and negative cases.- Guard READMEs document the new denial, and the generated skill copies plus their source digest are regenerated in sync.
| File | Description |
|---|---|
host-setup/agent-safety/claude/gh-write-guard.py |
Adds _overrides_hooks_path + _git_subcommand_invocations, wires the new deny into _check_bypass_flags, and adds self-test rows. Verified correct via direct execution and passing --selftest. |
.agents/skills/repo-worktree/SKILL.md |
Source-of-truth prose: shared-hook check, linked-worktree prohibition, commit-time override as bypass. |
.github/skills/repo-worktree/SKILL.md |
Generated copy, byte-identical to source (do not edit directly). |
.claude-plugin/fleet-skills/skills/repo-worktree/SKILL.md |
Generated copy, byte-identical to source. |
.claude-plugin/fleet-skills/.source-digests/repo-worktree |
Regenerated digest; reproduces exactly via build_dist.skill_digest. |
host-setup/agent-safety/README.md |
Requirement-4 prose extended to name the -c core.hooksPath= denial. |
host-setup/agent-safety/claude/README.md |
Guard bullet extended to name the core.hooksPath override denial. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…Deny a Commit-Time hooksPath Override (#2179) ## Summary Promotes develop to main, carrying [#2178](#2178). That PR stops `repo-worktree`'s hook step from installing into the git config or hooks directory a linked worktree shares with its base clone. Such an install rewrote the hook for every checkout. The skill now checks for an existing hook first, tells a linked worktree from a standalone clone, and lets only the standalone clone install locally. `gh-write-guard` now denies a commit-time `-c core.hooksPath=` or `--config-env` override on a commit or push, beside `--no-verify`. The remaining older bypass routes are filed as #2177. Fixes #1816 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Summary
Refs #1816.
repo-worktree"Preparing Git Hooks". A linked worktree shares the base clone's git config, and with nocore.hooksPathset it also shares the base clone's hooks directory. Runningpre-commit installthere rewrote the hook for every checkout. The section now:git rev-parse --git-path hooksbefore installing;--git-dirdiffering from--git-common-dir, both run from the root;core.hooksPathalready reads.husky;core.hooksPathoverride as a hook bypass.gh-write-guarddeniesgit -c core.hooksPath=... commit|pushand the--config-envforms beside--no-verify, with self-test rows. It refactors_git_subcommand_arglistsonto a new_git_subcommand_invocationsthat keeps the global options.The remaining bypass routes, all older than this change, are filed as #2177: a persistent
git config core.hooksPath, theGIT_CONFIG_*environment forms, wrapped or aliased git, and a heredoc false positive.Verification
gh-write-guard.py --selftestpasses. With the new check disabled, the four new deny rows fail.core.hooksPath.🤖 Generated with Claude Code