security-guidance plugin: git diff baseline gets confused across worktree switches, re-reports already-fixed findings

Status Open
Reported on v2.1.285
Maintainer reply None cached
Activity 1 comment · opened Oct 15, 2026

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-official v2.0.10
  • Python: 3.9.6
  • Provider: Anthropic API / subscription (default)

Repro scenario

A single long Claude Code session that:

  1. Starts in a normal repo checkout.
  2. Uses EnterWorktree/ExitWorktree several times to hop between multiple git worktrees of the same repo (a common pattern for isolating PR work).
  3. 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.js vulnerability had already been fixed and merged to main on 2026-10-08 (removed the vulnerable code path entirely).
  • mockupComments.js had 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 .git common 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_since against dirty_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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗