Refactor Claude Code Review workflow#1257
Conversation
Removed the step to delete prior Claude review comments and updated allowed tools for Claude Code Review.
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
📝 WalkthroughWalkthroughModified Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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 |
|
CodeAnt AI finished reviewing your PR. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/claude-code-review.yml (1)
18-22:⚠️ Potential issue | 🔴 CriticalCritical:
pull_request_target+ fork checkout +--dangerouslyDisableSandboxcreates a "pwn request" vulnerability.This workflow combines three dangerous elements documented by GitHub Security Lab as a high-risk pattern:
pull_request_targettrigger — Runs workflows in the context of the base repository with access to secrets and a write-scopedGITHUB_TOKEN. This is by design a privileged execution context.Checkout of the fork's HEAD (
ref: ${{ github.event.pull_request.head.sha }}, lines 18-22) — When combined withpull_request_target, this means untrusted PR code is executed with full access to repository secrets and elevated permissions, enabling token exfiltration or repo takeover.
--dangerouslyDisableSandbox(line 35) — Removes filesystem and network isolation that protects against prompt injection attacks. Even with--allowedToolsrestrictions, the sandbox was the last OS-level defense.Attack path: An external contributor opens a PR with embedded prompt-injection payloads in files (e.g., source code or
CLAUDE.md). Claude reads them via the allowedcat/find/greptools, gets manipulated to exfiltrate theGITHUB_TOKEN(which persists to disk in.git/configbecausepersist-credentials: falseis not set, defaulting totrue), or to post malicious comments using the write-scoped token. The absence of an author-association guard means this runs automatically for all external contributors.Additional risks:
- Lines 41-42:
gh api repos/*/issues/*/comments:*is an overly broad API wildcard that could allow Claude to operate on comments across multiple repositories.- Lines 18-22: No
persist-credentials: falsemeans theGITHUB_TOKENis stored in.git/config, accessible to any code executed during the workflow.- No
if:condition guards to limit the workflow to trusted contributors.Recommended mitigations (choose one or a combination):
- Add
persist-credentials: falseto the checkout step to prevent token storage on disk.- Remove
--dangerouslyDisableSandbox— it removes essential protections and was absent in prior versions for good reason.- Add an author-association guard so only trusted contributors trigger the privileged steps (e.g.,
if: github.event.pull_request.author_association == 'OWNER').- Split into an unprivileged
pull_requestworkflow (no secrets) for code review, and a privilegedworkflow_runor manual approval workflow for comment posting.🛡️ Minimum-impact hardening for the checkout step
- name: Checkout PR head (fork) uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 1 + persist-credentials: false🛡️ Remove the sandbox bypass from claude_args
claude_args: > - --dangerouslyDisableSandbox - --max-turns 10 + --max-turns 10 --allowedTools🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/claude-code-review.yml around lines 18 - 22, The workflow currently checks out the fork's HEAD (ref: ${{ github.event.pull_request.head.sha }}) under a privileged pull_request_target context and disables sandboxing via the claude_args flag (--dangerouslyDisableSandbox), creating a token-exfiltration vulnerability; to fix, change the checkout step to set persist-credentials: false to prevent GITHUB_TOKEN from being written to .git/config, remove the --dangerouslyDisableSandbox flag from claude_args, and add an author-association guard (e.g., if: github.event.pull_request.author_association == 'OWNER' or restrict to trusted associations) or split into an unprivileged pull_request workflow and a separate privileged workflow for posting comments; also narrow the gh api wildcard (gh api repos/*/issues/*/comments:*) to the specific repo/issue endpoints the workflow must use.
🧹 Nitpick comments (2)
.github/workflows/claude-code-review.yml (2)
63-74: Comment accumulation: prompt-based deduplication is less reliable than the removed programmatic cleanup.Without the prior-comment deletion step, every
synchronizepush creates a new comment instead of updating the existing one. The prompt instructs Claude to detect a prior comment and post"Claude Code Review (updated)", but this relies on Claude consistently reasoning about prior comments — which is not guaranteed across different model versions or context sizes.On an actively reviewed PR this will accumulate multiple review comments per push. Consider reinstating the programmatic deletion step (or using the
gh apito find and delete/update the previous comment before posting the new one) rather than depending on a prompt instruction.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/claude-code-review.yml around lines 63 - 74, The workflow currently relies on the model prompt to avoid duplicate comments which can cause repeated PR comments on each synchronize event; update the workflow step that posts the PR comment (the step that posts "Claude Code Review") to programmatically find and delete or update the prior comment before posting the new one (for example: add a step that uses the GitHub REST API or gh api to search for a prior comment by title/body and delete or PATCH it), or implement a dedicated “find-and-update” action prior to the post step so the existing comment is replaced instead of a new one being created.
26-32: Pinclaude-code-actionto a commit SHA to prevent supply-chain drift.
anthropics/claude-code-action@v1is a mutable tag that can be moved at any time by the maintainer or attacker with repository access. When the tag is moved, the next workflow run silently picks up whatever code it points to—including the plugin fetched at runtime. Combined with this workflow's elevated privileges (CLAUDE_CODE_OAUTH_TOKEN+pull-requests: write) and the--dangerouslyDisableSandboxflag, a silently-updated action is a significant supply-chain target.Use the commit SHA
1e78a9a73ab1efa7590f5c777b2ffe9d32084ef9(current v1 HEAD) or verify the latest:- uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@1e78a9a73ab1efa7590f5c777b2ffe9d32084ef9🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/claude-code-review.yml around lines 26 - 32, Replace the mutable tag anthropics/claude-code-action@v1 with the specific commit SHA to prevent supply-chain drift: change the uses reference to anthropics/claude-code-action@1e78a9a73ab1efa7590f5c777b2ffe9d32084ef9 (the current v1 HEAD) and keep the existing inputs (claude_code_oauth_token, github_token, plugin_marketplaces, plugins) unchanged; ensure the uses line in the workflow is the only change so the action is pinned to that exact commit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/claude-code-review.yml:
- Around line 41-42: The workflow exposes an overly broad gh api pattern
"Bash(gh api repos/*/issues/*/comments:*)" which permits arbitrary writes to
issue comments; tighten or remove it—either delete that pattern (since the
existing "gh pr comment" tool already handles posting PR comments) or replace it
with a method- and scope-restricted pattern that only allows POST to issue
comments for the specific repo, and likewise restrict "Bash(gh api
repos/*/pulls/*:*)" to only allow GET on pull requests (or target the specific
:owner/:repo) so the tools only permit the minimal required API verbs and
repository scope.
---
Outside diff comments:
In @.github/workflows/claude-code-review.yml:
- Around line 18-22: The workflow currently checks out the fork's HEAD (ref: ${{
github.event.pull_request.head.sha }}) under a privileged pull_request_target
context and disables sandboxing via the claude_args flag
(--dangerouslyDisableSandbox), creating a token-exfiltration vulnerability; to
fix, change the checkout step to set persist-credentials: false to prevent
GITHUB_TOKEN from being written to .git/config, remove the
--dangerouslyDisableSandbox flag from claude_args, and add an author-association
guard (e.g., if: github.event.pull_request.author_association == 'OWNER' or
restrict to trusted associations) or split into an unprivileged pull_request
workflow and a separate privileged workflow for posting comments; also narrow
the gh api wildcard (gh api repos/*/issues/*/comments:*) to the specific
repo/issue endpoints the workflow must use.
---
Nitpick comments:
In @.github/workflows/claude-code-review.yml:
- Around line 63-74: The workflow currently relies on the model prompt to avoid
duplicate comments which can cause repeated PR comments on each synchronize
event; update the workflow step that posts the PR comment (the step that posts
"Claude Code Review") to programmatically find and delete or update the prior
comment before posting the new one (for example: add a step that uses the GitHub
REST API or gh api to search for a prior comment by title/body and delete or
PATCH it), or implement a dedicated “find-and-update” action prior to the post
step so the existing comment is replaced instead of a new one being created.
- Around line 26-32: Replace the mutable tag anthropics/claude-code-action@v1
with the specific commit SHA to prevent supply-chain drift: change the uses
reference to
anthropics/claude-code-action@1e78a9a73ab1efa7590f5c777b2ffe9d32084ef9 (the
current v1 HEAD) and keep the existing inputs (claude_code_oauth_token,
github_token, plugin_marketplaces, plugins) unchanged; ensure the uses line in
the workflow is the only change so the action is pinned to that exact commit.
| "Bash(gh api repos/*/pulls/*:*)" | ||
| "Bash(gh api repos/*/issues/*/comments:*)" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's find and examine the workflow file
fd "claude-code-review.yml" --type fRepository: MFlowCode/MFC
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Examine the workflow file around lines 41-42
cat -n ".github/workflows/claude-code-review.yml" | sed -n '30,55p'Repository: MFlowCode/MFC
Length of output: 1296
🏁 Script executed:
#!/bin/bash
# Search for information about claude-code-action and how allowed-tool patterns work
rg -i "allowedTools|allowed-tool|gh api" --type yaml -A 2 -B 2Repository: MFlowCode/MFC
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check if there's documentation or configuration for the claude-code-action
fd "claude-code-action" -o -name "action.yml" -o -name "action.yaml" | head -20Repository: MFlowCode/MFC
Length of output: 287
🌐 Web query:
claude-code-action allowed-tool gh api syntax :*
💡 Result:
In Claude Code Action, allowed_tools uses Claude Code’s --allowedTools pattern syntax: for Bash commands you generally want the colon + wildcard form Bash(<prefix>:*) (not Bash(<prefix> *)). (skills.sh)
So to allow GitHub CLI gh api calls, use e.g.:
- uses: anthropics/claude-code-action@beta
with:
allowed_tools: |
Bash(gh api:*)If you want to be more restrictive (recommended), allow only specific methods/flags, for example:
allowed_tools: |
Bash(gh api --method GET:*)
Bash(gh api --method POST:*)(Example of this same pattern style for gh api appears in real-world configs/documentation.) (docs.rs)
Citations:
- 1: https://skills.sh/anthropics/claude-code/command-development?utm_source=openai
- 2: https://github.com/marketplace/actions/claude-code-action-yolo-mode?utm_source=openai
- 3: https://docs.rs/crate/octorus/0.3.4?utm_source=openai
🏁 Script executed:
#!/bin/bash
# Search for any documentation or README in the repo that might explain the allowed-tool syntax
fd -e md -e txt | xargs rg -l "allowedTools|allowed-tool|gh api" 2>/dev/null || trueRepository: MFlowCode/MFC
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check if there are any comments in the workflow file explaining the syntax
cat -n ".github/workflows/claude-code-review.yml" | head -60Repository: MFlowCode/MFC
Length of output: 2566
Overly broad gh api tool patterns could permit write operations on arbitrary issue comments.
"Bash(gh api repos/*/issues/*/comments:*)" allows Claude to call any gh api method on issue comments across all repos accessible by the token. This is broader than needed for posting a single PR comment.
The gh pr comment tool (line 40) already covers posting PR comments. If the gh api endpoint is still needed for specific cases, the patterns can be tightened to restrict both the scope and methods:
🔒 Restrict the API tool patterns to specific methods
- "Bash(gh api repos/*/pulls/*:*)"
- "Bash(gh api repos/*/issues/*/comments:*)"
+ "Bash(gh api --method GET repos/*/pulls/*:*)"
+ "Bash(gh api --method POST repos/*/issues/*/comments:*)"This limits operations to GET on pull requests and POST on issue comments, reducing the blast radius from prompt injection.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "Bash(gh api repos/*/pulls/*:*)" | |
| "Bash(gh api repos/*/issues/*/comments:*)" | |
| "Bash(gh api --method GET repos/*/pulls/*:*)" | |
| "Bash(gh api --method POST repos/*/issues/*/comments:*)" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/claude-code-review.yml around lines 41 - 42, The workflow
exposes an overly broad gh api pattern "Bash(gh api
repos/*/issues/*/comments:*)" which permits arbitrary writes to issue comments;
tighten or remove it—either delete that pattern (since the existing "gh pr
comment" tool already handles posting PR comments) or replace it with a method-
and scope-restricted pattern that only allows POST to issue comments for the
specific repo, and likewise restrict "Bash(gh api repos/*/pulls/*:*)" to only
allow GET on pull requests (or target the specific :owner/:repo) so the tools
only permit the minimal required API verbs and repository scope.
There was a problem hiding this comment.
Pull request overview
Refactors the Claude Code Review GitHub Actions workflow by simplifying rerun behavior and tightening/adjusting the tool allowlist while adding additional execution flags for the Claude action.
Changes:
- Removed the step that deleted a prior “Claude Code Review” PR comment before running.
- Added
--dangerouslyDisableSandboxand set--max-turns 10for the Claude run. - Narrowed
gh apiallowlist fromgh api:*to specific endpoint patterns and added guidance to use--repowith numeric PR commands.
| plugins: 'code-review@claude-code-plugins' | ||
|
|
||
| claude_args: > | ||
| --dangerouslyDisableSandbox |
There was a problem hiding this comment.
Using --dangerouslyDisableSandbox meaningfully increases the blast radius if the model is ever tricked into executing unsafe operations (especially with Bash(...) tools enabled). Prefer keeping the sandbox enabled; if disabling is truly required, add compensating controls (e.g., restrict workflow execution to trusted actors/branches, minimize GITHUB_TOKEN permissions, and further constrain allowed tools/commands) and document why sandboxing can’t be used here.
| --dangerouslyDisableSandbox |
| "Bash(gh api:*)" | ||
| "Bash(gh search code:*)" | ||
| "Bash(gh api repos/*/pulls/*:*)" | ||
| "Bash(gh api repos/*/issues/*/comments:*)" |
There was a problem hiding this comment.
The gh api ...:* patterns still allow arbitrary arguments/methods against these endpoints (including destructive methods like DELETE where applicable, and broad query construction). To reduce risk, constrain these to the minimal set of operations needed (e.g., only GET for reading PR metadata/diff, and only the specific POST needed for commenting), or remove gh api entirely if gh pr comment/view/diff cover the required behavior.
| "Bash(gh api repos/*/issues/*/comments:*)" |
| with: | ||
| ref: ${{ github.event.pull_request.head.sha }} | ||
| fetch-depth: 1 | ||
|
|
||
| - name: Remove prior Claude review comment (so review runs again) | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| pr=${{ github.event.pull_request.number }} | ||
| repo=${{ github.repository }} | ||
|
|
||
| # Find first issue comment whose body starts with "## Claude Code Review" | ||
| comment_id=$(gh api repos/$repo/issues/$pr/comments \ | ||
| --jq '.[] | select(.body | startswith("## Claude Code Review")) | .id' | head -n 1) | ||
|
|
||
| if [ -n "$comment_id" ]; then | ||
| echo "Deleting prior Claude review comment id=$comment_id" | ||
| gh api -X DELETE repos/$repo/issues/comments/$comment_id | ||
| else | ||
| echo "No prior Claude review comment found." | ||
| fi | ||
|
|
||
|
|
||
| - name: Run Claude Code Review |
There was a problem hiding this comment.
This removes the prior idempotency step that deleted the existing 'Claude Code Review' comment before running. That can lead to clutter across reruns (multiple top-level reviews) and makes the workflow behavior dependent on how the action posts comments. Consider restoring idempotent behavior by updating/editing an existing comment (preferred) or deleting the prior one before posting a new single top-level review.
CodeAnt-AI Description
Update Claude Code Review workflow: preserve previous comments and restrict allowed CLI actions
What Changed
Impact
✅ Preserve prior review comments so past feedback remains visible✅ Narrower CLI access during reviews reduces risk of broad repository operations✅ Clearer and more reliable review posting when previous reviews exist💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary by CodeRabbit
Note: This release contains no user-facing changes. Updates are infrastructure-related adjustments to development processes.