security-guidance plugin: git diff baseline gets confused across worktree switches, re-reports already-fixed findings
Summary
security-guidance's Stop-hook diff review loses track of its git "baseline" commit when the session's cwd moves between git worktrees mid-session (e.g. via Claude Code's EnterWorktree/ExitWorktree tool, or any workflow that cds between a repo's worktrees). When that happens, the next diff is computed against a stale/unrelated baseline commit instead of the worktree's actual previous state, producing a massively oversized and incoherent "changed files" set. In my case this caused the reviewer to re-report two vulnerabilities that had already been fixed and merged to main weeks earlier, as if they were present in the current diff.
Environment
- Claude Code CLI: 2.1.285
- Plugin:
security-guidance@claude-plugins-officialv2.0.10 - Python: 3.9.6
- Provider: Anthropic API / subscription (default)
Repro scenario
A single long Claude Code session that:
- Starts in a normal repo checkout.
- Uses
EnterWorktree/ExitWorktreeseveral times to hop between multiple git worktrees of the same repo (a common pattern for isolating PR work). - At one point the session's cwd is briefly the parent directory of several repos (not a git repo itself at all).
Evidence from ~/.claude/security/log.txt
Baseline capture failing outright when cwd was the non-repo parent directory:
[2026-10-15 14:51:54.497] No commits in repo, skipping baseline capture
[2026-10-15 14:51:54.539] _list_untracked rc=128: fatal: not a git repository (or any of the parent directories): .git
[2026-10-15 14:51:54.645] Failed to capture git baseline (cwd='/Users/williamloopesko/Development') — not a git repo, or git invocation failed (check log entries above)
Shortly after, the baseline gets re-captured against some other commit, and the very next Stop-hook review has a wildly inflated changed_since relative to the actual dirty-file count:
[2026-10-15 14:52:42.955] Captured git baseline: 7d7f8f0da773
[2026-10-15 14:52:46.134] Stop hook: review_set=139 base=HEAD dirty_now=139 changed_since=1020
[2026-10-15 14:52:46.632] Stop hook: prioritized to 30 files (dropped 106 lower-risk)
Another instance a few minutes earlier in the same session:
[2026-10-15 14:19:45.774] Stop hook: review_set=138 base=HEAD dirty_now=138 changed_since=448
[2026-10-15 14:19:46.092] Stop hook: prioritized to 30 files (dropped 105 lower-risk)
In both cases dirty_now (actual working-tree changes) is far smaller than changed_since (the baseline-relative diff), which only makes sense if the baseline commit being diffed against belongs to an unrelated point in history — most likely a commit from a different worktree/branch that happened to be cwd when an earlier baseline capture fired.
Observed impact
The reviewer surfaced "new" HIGH/CRITICAL findings (spoofable-field auth in functions/src/agentPlatform/endpoints/_shared.js, and in functions/src/comments/mockupComments.js) on a turn where neither file had been touched. On investigation:
- The
_shared.jsvulnerability had already been fixed and merged tomainon 2026-10-08 (removed the vulnerable code path entirely). mockupComments.jshad been deleted from the repo entirely over a month earlier (2026-09-09).
Both findings were confirmed stale by checking git log/git show against current origin/main and against the actual worktree branches in use — the fix commits were ancestors of every branch the session was working on. The only plausible explanation is the diff-review comparing against a baseline commit that predates those fixes, inherited from a different worktree context.
This repeated across at least two separate turns in the same session, each time re-surfacing the same already-fixed findings, which is confusing and erodes trust in the tool's output (it looks like a regression or a review of unrelated code).
Suggested fix
- When capturing or reusing a git baseline, validate that the baseline commit is actually an ancestor of (or otherwise meaningfully related to) the current cwd's
HEAD/worktree — not just whatever commit happened to be captured last, regardless of which worktree/repo root was active at the time. - If cwd has moved to a different git worktree (different
.gitcommon dir resolution, or a worktree list entry different from the one the baseline was captured in), invalidate/re-capture the baseline rather than carrying it forward. - Consider sanity-checking
changed_sinceagainstdirty_now— a large divergence between the two is a strong signal the baseline is stale/wrong, and the hook could fall back to a same-worktree-only diff (or skip review with a log note) rather than reviewing a nonsensical diff.
Happy to provide the full log file privately if useful — trimmed the excerpts above to the relevant lines since the log also contains unrelated session activity.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗