Skip to content

fix: resolve the diff base from origin/HEAD instead of assuming main - #217

Open
withinfocus wants to merge 1 commit into
mainfrom
fix/resolve-diff-base-ref
Open

fix: resolve the diff base from origin/HEAD instead of assuming main#217
withinfocus wants to merge 1 commit into
mainfrom
fix/resolve-diff-base-ref

Conversation

@withinfocus

@withinfocus withinfocus commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Both review paths diffed against a hardcoded main. On a repository whose default branch is named something else, or a branch cut from rc, they reviewed the wrong range.

perform-security-review gains --base-ref and otherwise resolves the base from an ordered candidate list: origin/HEAD first, then the repository default branch via gh repo view. Every candidate passes an allowlist before it reaches a command, then rev-parse --verify, then merge-base. If none passes, the run stops and says so instead of writing a zero-byte diff that four agents then review as clean.

The reviewer agent's local mode diffs origin/HEAD...HEAD and passes the symbolic ref straight to git rather than resolving it to a name first. An empty result counts as a failure, not a clean review.

Quoting the argument-hint in both commands fixed frontmatter that had never parsed, which made their allowed-tools live for the first time and put every grant in those files under review. gh api and rm are gone. Any wildcard in an allowed-tools rule absorbs an inserted flag, so no rule can constrain gh api's verb; references/tool-grants.md shows the bypass. GHAS scan evidence now prompts, and CI records it as not checked rather than as nothing found.

/code-review no longer resolves a pull request from the checkout. Both commands pass the resolved target on a TARGET: line, and /code-review-local adds OUTPUT: local files so its review cannot reach a GitHub comment.

bitwarden-code-review 1.14.1 to 2.0.0 and bitwarden-security-engineer 1.3.0 to 2.0.0. Major on both, for the removed grants and the changed resolution.

@withinfocus withinfocus added the ai-review Request a Claude code review label Aug 26, 2026
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed this head against the files rather than the thread replies: the reviewer agent's TARGET:/OUTPUT: contract and rewritten local-mode procedure with references/local-mode-diff.md, both slash commands and their READMEs, posting-review-summary's ## No Verdict form and its two new local-output routing rows, and perform-security-review's sub-step A2 with references/base-ref-resolution.md and references/tool-grants.md. All 49 prior threads are addressed at this head — the pr_number resolution order in code-review.md:19-21 now matches the changelog entry, the local-mode read cap counts what survives the extension allow-list rather than the raw ?? set, and AGENT.md:27 grounds the ^[0-9]+$ gate on Bash(gh pr view:*) being a prefix rule. Every grant was checked against what each file runs: the agent's tools: is the same 15 entries alphabetized with no widening, code-review holds only Read(//tmp/pr-threads.json) and Task with the double-slash absolute form, code-review-local only AskUserQuestion and Task, and the security skill's git rev-parse, git merge-base, gh repo view --json defaultBranchRef, and exact-match printenv GITHUB_ACTIONS grants are read-only across their argument space with gh api and rm gone; neither command interpolates an argument into a shell string, no credentials appear in any of the eight changed configuration files, no changed file attempts to direct this review, every referenced file and skill resolves, and version bumps, changelog entries, catalog rows, and the three new cspell terms are consistent across both plugins. The four findings below are record and consistency defects, not regressions in capability.

Not covered: Skill review did not run — this review path cannot launch plugin-dev:skill-reviewer, so plugins/bitwarden-code-review/skills/posting-review-summary/SKILL.md and plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md were not checked for description quality, length, or progressive disclosure. performing-multi-agent-code-review covers them where plugin-dev is installed.

Code Review Details
  • ♻️ : The local-file redirect for inline comments exists only at the call site; posting-bitwarden-review-comments/SKILL.md was left saying post to GitHub, unlike the summary skill that got a routing row in this same change
    • plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md:194
  • ♻️ : Duplicated instruction, and "APPROVE or REQUEST CHANGES" names a verdict this skill's report template does not define
    • plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md:71
  • ♻️ : Changelog records the superseded github-only abort routing; both aborts write to the resolved destination
    • plugins/bitwarden-security-engineer/CHANGELOG.md:24
  • ♻️ : Migration guidance stated twice in one bullet, and four scan-evidence calls counted where SKILL.md says three run
    • plugins/bitwarden-security-engineer/CHANGELOG.md:29

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

🤖 Bitwarden Claude Code Review

Overall Assessment: REQUEST CHANGES

Reviewed the base-ref change at this head against the files rather than the thread replies. bitwarden-code-reviewer local mode now passes the symbolic origin/HEAD to git without interpolating a resolved name, gates on content as well as exit status, falls back to git diff HEAD plus git status --porcelain --untracked-files=all with a credential-material skip list, and otherwise aborts through Skill(posting-review-summary) with no verdict; perform-security-review resolves its base in sub-step A2 behind the ^[A-Za-z0-9_][A-Za-z0-9._/-]*$ allowlist, git rev-parse --verify, and a git merge-base gate, with --base-ref, a mode-conflict stop, and a vs {base-ref} step 5 header. Every grant was checked against what each file runs: the three gh api entries parse as strings and pin their endpoint paths, the new git rev-parse, git merge-base, gh repo view --json defaultBranchRef, and printenv GITHUB_ACTIONS grants are read-only across their argument space, both commands are narrowed to the tools their own turns use, and the agent's tools: set is reordered without widening — 15 entries before and after. All 30 prior threads are addressed at this head, including the mode-list indentation in the one still open; no credentials appear in any changed file, version bumps and catalog entries are consistent for both plugins, and no changed file attempts to direct this review.

Not covered: Skill review did not run — this review path cannot launch plugin-dev:skill-reviewer, so plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md and plugins/bitwarden-code-review/skills/posting-review-summary/SKILL.md were not checked for description quality, length, or progressive disclosure. performing-multi-agent-code-review covers them where plugin-dev is installed.

Code Review Details
  • ⚠️ : The TARGET: line the command now emits has no consumer, and the "stacked-PR gate" it cites exists nowhere in the plugin
    • plugins/bitwarden-code-review/commands/code-review/code-review.md:41
  • ♻️ : Changelog says the agent's grants became a YAML list, four lines after the entry saying they stayed a comma-separated string
    • plugins/bitwarden-code-review/CHANGELOG.md:23

PR Metadata Assessment

  • QUESTION: Two lines of the description are stale against the diff — it closes with "bitwarden-security-engineer 1.3.0 to 1.3.1" where the diff bumps to 1.4.0 (the diff is right; --base-ref is a MINOR add), and the "A path that has no origin/HEAD" bullet still describes a gh api default_branch fallback that "prompts only on interactive runs", where A2 now uses gh repo view and never prompts.

Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch from 2c29796 to 6332774 Compare August 27, 2026 14:15
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch 2 times, most recently from 4244054 to 8ef7114 Compare August 27, 2026 14:53
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch 3 times, most recently from 30cb4ee to bfc1a4a Compare August 27, 2026 16:08
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
Base automatically changed from fix/code-review-local-git-status to main August 27, 2026 18:16
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch 3 times, most recently from 96ec72f to ef55ed0 Compare August 27, 2026 18:21
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch from 290ff29 to 350b792 Compare September 1, 2026 19:12
Comment thread plugins/bitwarden-security-engineer/skills/perform-security-review/SKILL.md Outdated
Comment thread plugins/bitwarden-code-review/commands/code-review/code-review.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch from 350b792 to f4e9b0e Compare September 1, 2026 19:42
Comment thread plugins/bitwarden-code-review/commands/code-review/code-review.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch from f4e9b0e to 004faff Compare September 1, 2026 21:20
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
@withinfocus
withinfocus marked this pull request as draft September 1, 2026 21:31
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch 2 times, most recently from 0d5e4de to 7757699 Compare September 1, 2026 22:19
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch 3 times, most recently from 7152a18 to be12975 Compare September 2, 2026 12:20
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch 2 times, most recently from 737c13c to 742202e Compare September 2, 2026 13:29
Comment thread plugins/bitwarden-code-review/agents/bitwarden-code-reviewer/AGENT.md Outdated
Comment thread plugins/bitwarden-code-review/CHANGELOG.md Outdated
Local-mode code review and branch-comparison security review both diffed
against a literal `main`, which is the wrong base in any repo whose default
branch is named something else. Both now resolve `origin/HEAD` and ask when
it cannot be resolved, and both gained the `git symbolic-ref` grant needed
to run that resolution.
@withinfocus
withinfocus force-pushed the fix/resolve-diff-base-ref branch from 742202e to f83c636 Compare September 2, 2026 14:02
@withinfocus
withinfocus marked this pull request as ready for review September 2, 2026 15:04
- For 🎨 SUGGESTED and ❓ QUESTION: Never reopen after human provides answer/decision

Invoke `Skill(posting-bitwarden-review-comments)` to format and post each validated finding as an inline comment.
Invoke `Skill(posting-bitwarden-review-comments)` to format and post each validated finding as an inline comment. If the output destination in effect is local files — declared in the prompt, or set by entering local mode in Step 1 — format them the same way but write them to `review-inline-comments.md` in the working directory instead of posting.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ DEBT: The local-file redirect for inline comments exists only at this call site; the skill it loads still says post to GitHub.

Details and fix

This changeset made the destination authoritative inside the skill for the summary path — skills/posting-review-summary/SKILL.md:14 gained a first routing row keyed on OUTPUT: local files, and its description was updated to name "caller-declared local-file output". The inline path got the opposite treatment: skills/posting-bitwarden-review-comments/SKILL.md is untouched, so its description still reads "Use this skill when posting inline comments to GitHub pull requests", its body is headed "GitHub Comment Posting Protocol", and rule 2 is "MUST Use inline comments for code-specific findings". It contains no local destination at all.

So on /code-review-local 123TARGET: PR #123 plus OUTPUT: local files, which line 21 of that command always appends — the agent enters PR mode, reaches this step, and loads a skill whose entire text says post, while still holding mcp__github_inline_comment__create_inline_comment. Only the sentence on this line stands between that and a comment on a command documented as never posting, which is weaker than the binding line 42 calls "the control".

Fix: add a destination row to skills/posting-bitwarden-review-comments/SKILL.md mirroring the one added to posting-review-summary/SKILL.md, so the skill is authoritative on where its own output lands rather than depending on the caller restating it.


In those three cases, and only those, clear the diff file with step 7's `Write` before stopping. On the success path it must survive: steps 2 and 4 hand its path to the agents.

Report as the step 1-A2 abort does, to the resolved output destination. Stopping here skips step 5, so add the `Pending changes: not reviewed` note when the tree was dirty. Emit no assessment. Emit no APPROVE or REQUEST CHANGES assessment; nothing was reviewed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ DEBT: This line ends with the same instruction twice, and the second names a verdict this skill's report does not define.

Details and fix

As written: Emit no assessment. Emit no APPROVE or REQUEST CHANGES assessment; nothing was reviewed.

Two problems:

  • The first sentence is a duplicate of the second.
  • "APPROVE or REQUEST CHANGES" names nothing in this skill. Step 5's report template (lines 139-196) defines only the Summary count table plus 🚨 Blockers / ⚠️ Improvements / 📝 Notes / ✅ Strengths / ❌ Dismissed — no approve/request-changes verdict anywhere. That vocabulary belongs to bitwarden-code-review's posting-review-summary, whose template does use it, so this reads as a copy across plugins. A model following the line has nothing to suppress, and may infer such a verdict is normally expected here.

Suggested replacement naming a construct that exists:

   Report as the step 1-A2 abort does, to the resolved output destination. Stopping here skips step 5, so add the `Pending changes: not reviewed` note when the tree was dirty. Emit no summary table and no findings sections; nothing was reviewed.

- Every candidate passes a `git merge-base` gate, so a shallow clone cannot yield a zero-byte diff reviewed as clean
- Every candidate passes an `^[A-Za-z0-9_][A-Za-z0-9._/-]*$` allowlist before reaching a command; a legal ref name can still be a shell payload or a leading-dash option
- Step 1B checks exit status and content before launching agents, and clears the diff file's contents on every abort path
- Step 1B and the step 1-A2 abort both write their reason to the `github` output destination, since stopping skips step 6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ DEBT: This entry records the superseded routing — both aborts write to the resolved destination, not to github.

Details and fix

SKILL.md:55 (the A2 abort): "Write it to the resolved output destination, the same one a completed review would use." SKILL.md:71 (the 1B stops): "Report as the step 1-A2 abort does, to the resolved output destination."

github is one of three outcomes there, and the change away from keying on the environment was deliberate — the thread that drove it closed with "I also changed the gate on both paths from the bare GITHUB_ACTIONS check to the resolved destination, since step 6 gives an explicit --output chat precedence over the environment variable." This bullet is the only place that still records the earlier design, so a reader consulting it concludes an abort under --output file or chat reports nowhere.

Suggested change
- Step 1B and the step 1-A2 abort both write their reason to the `github` output destination, since stopping skips step 6
- Step 1B and the step 1-A2 abort both write their reason to the resolved output destination, since stopping skips step 6


### Removed

- The `Bash(gh api --method GET *)` and `Bash(rm -f /tmp/security-review-*)` grants, with no replacement. Step 7 clears the temp diff with the granted `Write` tool instead, so cleanup still runs unattended. **Migration:** a deployment that needs GHAS evidence on the unattended path must add its own `gh api` allow rule and pair it with a read-only `GH_TOKEN`. Any `allowed-tools` wildcard absorbs an inserted `-X DELETE`, so no rule can constrain the verb — `references/tool-grants.md` shows the bypass. Step 1-C's four scan-evidence calls now prompt, and in CI they are denied and render as `Not checked (permission denied)` rather than `None`. A deployment that wants GHAS evidence unattended should control it with a read-only `GH_TOKEN` and its own narrow grant

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ DEBT: This bullet states the migration guidance twice and counts four scan-evidence calls where SKILL.md says three run.

Details and fix

The GH_TOKEN guidance appears at both ends of the same bullet:

Migration: a deployment that needs GHAS evidence on the unattended path must add its own gh api allow rule and pair it with a read-only GH_TOKEN.

A deployment that wants GHAS evidence unattended should control it with a read-only GH_TOKEN and its own narrow grant

Same instruction, ~70 words apart, in the one bullet a reader on a pinned version consults for what they have to do.

The count is also off against the skill: SKILL.md:75 reads "Three run per invocation: code scanning takes either the PR-mode or the ref-mode form." Four commands are listed, three prompt, so three are denied in CI — which is the number that matters here, since it is the number of Not checked (permission denied) rows the report renders.

Fix: change "four scan-evidence calls" to "three", and drop the trailing sentence in favour of the **Migration:** one, which already carries it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant