Skip to content

Conversation

@bartlomieju
Copy link
Member

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Nov 21, 2025

Walkthrough

This change introduces a new GitHub Actions workflow for automated PR reviews using Claude AI and adds settings.json to the repository's .gitignore. The workflow automatically triggers on pull request events, sets up Node.js, installs Claude Code and a GitHub MCP server, configures the MCP with GitHub token credentials, and executes Claude Code Review with restricted tool access. The .gitignore update prevents committing Claude configuration files to the repository.

Sequence Diagram

sequenceDiagram
    participant GitHub as GitHub Actions
    participant Checkout as Checkout Repo
    participant Node as Setup Node.js
    participant Claude as Install Claude Code
    participant Config as Configure MCP
    participant Prompt as Create Prompt
    participant Review as Run Claude Review
    participant API as Anthropic API

    GitHub->>Checkout: Fetch repository (depth 1)
    Checkout-->>GitHub: Repository ready
    GitHub->>Node: Setup Node.js v24
    Node-->>GitHub: Node ready
    GitHub->>Claude: Install Claude Code & MCP server
    Claude-->>GitHub: Installation complete
    GitHub->>Config: Configure settings.json with GITHUB_TOKEN
    Config-->>GitHub: MCP configured
    GitHub->>Prompt: Create /tmp/prompt.txt with PR details
    Prompt-->>GitHub: Prompt file ready
    GitHub->>Review: Run Claude Code Review
    Review->>API: Call Anthropic API with review request
    API-->>Review: Review analysis
    Review-->>GitHub: Review complete
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify workflow trigger conditions and permissions are appropriate for PR reviews
  • Confirm Claude Code and MCP server versions are pinned or stable
  • Review environment variable handling (GITHUB_TOKEN, ANTHROPIC_API_KEY) for security best practices
  • Check tool restrictions in the workflow accurately match intended scope

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive No pull request description was provided by the author; while some context exists in the PR metadata and objectives, the actual description field is empty. Add a brief description explaining the purpose of the Claude PR review workflow and its intended behavior for automated PR reviews.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ci: add Claude PR reviews' clearly and concisely describes the main change: adding a GitHub Actions workflow for automated PR reviews using Claude.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude_pr_review

Comment @coderabbitai help to get the list of available commands and usage tips.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

Security and Code Quality Review

I've reviewed this GitHub Actions workflow for Claude PR reviews. Here are my findings:

🔴 Critical Security Issues

  1. Using pull_request instead of pull_request_target (.github/workflows/claude_pr_review.yml:4-5)

    • The workflow uses pull_request trigger with checkout of PR branch
    • This is vulnerable to code injection attacks from untrusted PRs
    • Malicious PRs could modify workflow files or inject commands
    • Recommendation: Use pull_request_target which runs in the context of the base repository
    • See your own pr.yml workflow for the correct pattern with warning comment
  2. Insufficient input validation (.github/workflows/claude_pr_review.yml:32-47)

    • Variables are interpolated directly into the prompt file
    • Recommendation: Follow the pattern in ai_pr_generation.yml which uses environment variables and proper escaping
  3. Unrestricted tool access (.github/workflows/claude_pr_review.yml:56)

    • The workflow grants access to inline comments and gh commands
    • Recommendation: Consider additional safeguards or sandbox constraints

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

⚠️ Medium Priority Issues

  1. Shallow checkout depth (.github/workflows/claude_pr_review.yml:17-18)

    • fetch-depth: 1 may limit the AI's ability to understand context
    • Recommendation: Consider fetch-depth: 0 or a reasonable depth like 50
  2. Missing error handling

    • No failure notification like in ai_pr_generation.yml
    • Users won't know if the review failed
    • Recommendation: Add a failure notification step
  3. No concurrency control

    • Multiple review runs could conflict if PR is updated rapidly
    • Recommendation: Add concurrency group
  4. Missing checkout of PR head

    • The workflow checks out the default branch, not the PR branch
    • AI won't see the actual PR changes
    • Recommendation: Add proper PR checkout configuration

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

💡 Best Practices

  1. Node.js version 24

    • Node.js 24 doesn't exist yet (current is 22)
    • Recommendation: Use node-version: '22' or 'lts/*'
  2. Missing timeouts on steps

    • Individual steps don't have timeouts
    • Recommendation: Add timeouts to npm install and other steps
  3. Actions versions inconsistency

    • Uses actions/checkout@v5 while ai_pr_generation.yml uses @v4
    • Not a bug, but consider consistency across workflows

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

📋 Summary

This workflow has critical security vulnerabilities that need to be addressed before merging:

Main issue: Using pull_request trigger allows untrusted code execution from malicious PRs

Required changes:

  1. Change to pull_request_target trigger
  2. Add ref parameter to checkout step to checkout PR head SHA
  3. Add concurrency control to prevent conflicts
  4. Add environment variable handling and proper escaping (follow ai_pr_generation.yml pattern)
  5. Add failure notification step
  6. Fix Node.js version to 22 or lts
  7. Increase fetch-depth for better context

Please reference your existing ai_pr_generation.yml workflow which implements these security patterns correctly.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

🔍 Detailed Issue: pull_request vs pull_request_target

Line 4: Using pull_request: trigger is a critical security vulnerability

Attack scenario:

  1. Attacker forks the repo and creates a malicious PR
  2. In their fork, they modify .github/workflows/claude_pr_review.yml
  3. They add code to exfiltrate secrets
  4. When the PR is opened, the workflow runs with the MODIFIED workflow file from the PR
  5. Secrets are leaked

Your pr.yml already has the correct pattern with a warning comment on line 10-11 about running in the context of the base repository.

The difference:

  • pull_request: Runs the workflow from the PR branch (dangerous)
  • pull_request_target: Runs the workflow from the base branch (safe)

Then you checkout the PR code explicitly in a controlled way.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

🔍 Detailed Issue: Missing PR Checkout

Line 16-18: Checkout configuration is incomplete

Currently:

- uses: actions/checkout@v5
  with:
    fetch-depth: 1

This checks out the default branch (main), not the PR branch. The AI reviewer won't see any of the PR changes.

What you need:

- uses: actions/checkout@v5
  with:
    ref: [PR_HEAD_SHA_VARIABLE]
    fetch-depth: 50  # or 0 for full history

Without this, the workflow will review the main branch, not the PR changes.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

🔍 Detailed Issue: Node.js Version

Line 23: node-version: '24'

Node.js version 24 does not exist yet. The current versions are:

  • Latest LTS: v22.x
  • Previous LTS: v20.x
  • Current: v23.x (odd numbers are non-LTS)

This will cause the workflow to fail.

Recommendation: Use node-version: '22' or node-version: 'lts/*' for automatic LTS selection.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

🔍 Detailed Issue: Input Validation and Injection

Line 32-47: Prompt construction with insufficient validation

The current code directly interpolates GitHub context variables into a heredoc:

cat > /tmp/prompt.txt << 'EOF'
REPO: [GITHUB_REPO_VAR]
PR NUMBER: [PR_NUMBER_VAR]

While the single-quoted heredoc prevents shell expansion inside the heredoc, the outer variables are still expanded by GitHub Actions before the heredoc.

Compare with ai_pr_generation.yml (lines 62-96):

  • Uses environment variables to pass untrusted data
  • Uses base64 encoding for multiline content
  • Validates format before use
  • Sanitizes inputs

Recommendation: Follow the same pattern with environment variables and validation as in your ai_pr_generation.yml workflow.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

✅ Positive Aspects

While there are critical issues to address, some things are done well:

  1. Appropriate permissions (lines 11-14): Minimal permissions granted - read for contents, write for PRs
  2. Timeout set (line 10): 60-minute timeout prevents runaway workflows
  3. Modern actions version: Using actions/checkout@v5 is good (though consistency with @v4 in other workflows would be nice)
  4. Scoped tool access (line 56): Restricting Claude to specific tools is good security practice
  5. Clear prompt structure (lines 36-46): Well-organized review criteria

The workflow has good bones - it just needs security hardening before it can be safely deployed.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

🛠️ Recommended Action Items

Before merging, please address these in priority order:

P0 - Critical (Must Fix):

  1. ✅ Change pull_request to pull_request_target (line 4)
  2. ✅ Add proper PR checkout with ref parameter (line 16)
  3. ✅ Fix Node.js version from 24 to 22 (line 23)

P1 - High (Should Fix):
4. Add concurrency control to prevent race conditions
5. Add failure notification step (see ai_pr_generation.yml lines 354-363)
6. Improve input validation with environment variables

P2 - Medium (Nice to Have):
7. Increase fetch-depth from 1 to 50 or 0
8. Add step timeouts for npm install and Claude execution
9. Consider consistency with checkout@v4 across workflows

Reference implementations:

  • Security patterns: ai_pr_generation.yml
  • Simple PR workflow: pr.yml

Would you like me to prepare a corrected version of the workflow?

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

Overall Assessment

This PR adds automated Claude-based PR reviews to the Deno repository. The implementation is generally well-structured, but I've identified several important issues that should be addressed.

Critical Issues

  1. Security: Variable Substitution in MCP Config - The GITHUB_TOKEN environment variable substitution in the MCP configuration (line 44) uses shell-style syntax within a JSON string, but this won't actually work as expected in the runtime context.

  2. Race Condition Risk - The workflow will trigger on every PR open/update without any concurrency control. This could lead to multiple Claude reviews running simultaneously on the same PR.

Major Concerns

  1. Missing Checkout Configuration - The workflow checks out with fetch-depth: 1, which only retrieves the latest commit. This limits Claude's ability to understand the full context of changes.

  2. Node Version Constraint - The workflow specifies Node.js version '24', which doesn't exist yet (current is v23). This will cause the workflow to fail.

  3. Cost Control - There's no mechanism to limit which PRs get reviewed. Every PR will trigger an expensive AI review.

Recommendations

  1. Error Handling - No error handling or failure notifications if Claude fails to review.

  2. Rate Limiting - Consider adding a check for PR size/complexity to avoid reviewing massive PRs.

I'll add inline comments on specific issues.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

Specific Code Issues

Line 10: Timeout Duration

  • 60 minutes is very generous for a PR review. Consider reducing to 30 minutes to prevent runaway costs if something goes wrong.

Line 18: Shallow Checkout

  • fetch-depth: 1 limits context. Consider using fetch-depth: 0 or at least fetch-depth: 10 to give Claude more history.

Line 23: Invalid Node Version

  • Node.js v24 does not exist yet. Change to 20 or 22 (LTS versions) or 23 (latest).

Line 44: Environment Variable Substitution

  • CRITICAL: The JSON will contain the literal string for GITHUB_TOKEN variable reference. The shell-style variable substitution won't work in this context. You need to either use envsubst to substitute variables before writing the JSON, or generate the JSON dynamically with proper variable expansion.

Lines 8-14: Missing Concurrency Control

  • Add a concurrency group to prevent multiple reviews on the same PR running simultaneously.

Line 74: Token Usage

  • Using DENOBOT_PAT for GitHub operations is good, but ensure this token has minimal required permissions.

Missing: PR Size Check

  • Consider adding a step to check PR size before running the review. Large PRs could be expensive or hit token limits.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

Additional Suggestions

Security Considerations:

  1. The workflow runs on all PRs without filtering. Consider adding conditions to only run on:

    • PRs from trusted contributors
    • PRs with a specific label (e.g., ai:review)
    • PRs below a certain size threshold
  2. The ANTHROPIC_API_KEY is exposed to the workflow. Ensure this secret has appropriate rate limiting and cost controls on the Anthropic side.

Performance Optimizations:

  1. Consider caching the npm packages (claude-code and github MCP server) to speed up workflow execution.

  2. The --allowedTools flag is restrictive (good for security), but might limit Claude's ability to effectively review code. You may need to iterate on what tools are needed.

Comparison with ai_pr_generation.yml:

  • The existing AI workflow has much more sophisticated error handling, input validation, and security measures.
  • Consider adopting similar patterns for concurrency control, timeouts, and failure handling.
  • The existing workflow uses actions/checkout@v4, but this one uses @v5. Ensure consistency across workflows.

Testing:

  • Before merging, test this workflow on a fork or with a label-based trigger to avoid unexpected costs.
  • Verify the MCP configuration actually works with the token passing mechanism.

Documentation:

  • Consider adding a comment at the top of the workflow explaining when it runs and how to disable it if needed.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

.gitignore Change

The addition of .claude/settings.json to .gitignore (line 48) is appropriate since the workflow dynamically generates this file with secrets.

However, note that line 47 already ignores .claude/settings.local.json. Consider documenting the difference between these two files:

  • settings.json: Generated by CI/workflows (now ignored)
  • settings.local.json: User-specific local settings (already ignored)

This change is good and prevents accidentally committing generated configuration with sensitive tokens.

@denobot
Copy link
Collaborator

denobot commented Nov 21, 2025

Summary and Action Items

Must Fix Before Merge:

  1. Fix Node.js version - Change from 24 to a valid version (20, 22, or 23)
  2. ⚠️ Fix GITHUB_TOKEN substitution - The current approach won't work. Need proper variable expansion in the MCP config
  3. 🔄 Add concurrency control - Prevent multiple simultaneous reviews on the same PR

Strongly Recommended:

  1. 🎯 Add PR size/trigger filtering - To control costs and avoid reviewing every PR automatically
  2. 🛡️ Reduce timeout - 60 minutes is excessive, consider 30 or less
  3. 📚 Increase fetch-depth - fetch-depth: 1 limits Claude's ability to understand context

Nice to Have:

  1. Add npm caching - Speed up workflow execution
  2. 📝 Add workflow documentation - Explain purpose and how to use/disable
  3. 🔍 Test on a fork first - Validate the MCP token passing works before production use

The workflow is a good starting point, but issues 1-3 are critical and must be addressed for it to function correctly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
.github/workflows/claude_pr_review.yml (1)

25-31: Add timeouts to npm install steps.

Long npm installs can hang. Add timeouts to fail fast and avoid blocking other workflows.

Apply this diff to the Install Claude Code step:

       - name: Install Claude Code
+        timeout-minutes: 10
         shell: bash
         run: npm install -g @anthropic-ai/claude-code
       
       - name: Install GitHub MCP Server
+        timeout-minutes: 10
         shell: bash
         run: npm install -g @modelcontextprotocol/server-github
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e59d37f and ff3e40f.

📒 Files selected for processing (2)
  • .github/workflows/claude_pr_review.yml (1 hunks)
  • .gitignore (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: test debug linux-aarch64
  • GitHub Check: test debug linux-x86_64
  • GitHub Check: test debug windows-x86_64
  • GitHub Check: test release macos-x86_64
  • GitHub Check: test debug macos-x86_64
  • GitHub Check: build libs
  • GitHub Check: test debug macos-aarch64
  • GitHub Check: lint debug macos-x86_64
  • GitHub Check: lint debug windows-x86_64
  • GitHub Check: lint debug linux-x86_64
  • GitHub Check: review
🔇 Additional comments (2)
.gitignore (1)

47-48: LGTM. Simple addition that prevents Claude configuration files from being committed, aligning with the new workflow's use of settings.json.

.github/workflows/claude_pr_review.yml (1)

20-23: Node.js version '24' does not exist; use '22' or 'lts/*'.

Node.js v24 is not a valid release version. Use v22 LTS or the lts/* specifier.

Apply this diff:

       - name: Setup Node.js
         uses: actions/setup-node@v4
         with:
-          node-version: '24'
+          node-version: '22'

Likely an incorrect or invalid review comment.

Comment on lines +3 to +5
on:
pull_request:
types: [opened, synchronize]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Switch to pull_request_target with controlled PR checkout.

The pull_request trigger runs the workflow code from the PR branch, allowing untrusted code execution and token exfiltration attacks. Use pull_request_target to run from the base branch, then explicitly checkout the PR head with a safe ref.

Apply this diff:

 on:
-  pull_request:
+  pull_request_target:
     types: [opened, synchronize]

Then update the checkout step (see the next comment) to explicitly fetch the PR head.

📝 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.

Suggested change
on:
pull_request:
types: [opened, synchronize]
on:
pull_request_target:
types: [opened, synchronize]
🤖 Prompt for AI Agents
.github/workflows/claude_pr_review.yml lines 3-5: the workflow currently uses
the pull_request trigger which runs workflow code from the PR branch and can
execute untrusted code; change the trigger to pull_request_target so the
workflow runs from the base branch, and then update the checkout step to
explicitly fetch and checkout the PR head (use actions/checkout with ref:
github.event.pull_request.head.sha or github.event.pull_request.head.ref and
fetch-depth: 0 and token: ${{ secrets.GITHUB_TOKEN }}) to safely run the PR
changes while keeping workflow code executed from the base branch.

Comment on lines +16 to +18
- uses: actions/checkout@v5
with:
fetch-depth: 1
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Add PR head ref and increase fetch-depth for better context.

The current checkout defaults to the base branch and uses a shallow clone. You need to explicitly checkout the PR head so Claude sees the PR changes. Also increase fetch-depth to provide more context.

Apply this diff:

       - uses: actions/checkout@v5
         with:
-          fetch-depth: 1
+          fetch-depth: 0
+          ref: ${{ github.event.pull_request.head.sha }}
📝 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.

Suggested change
- uses: actions/checkout@v5
with:
fetch-depth: 1
- uses: actions/checkout@v5
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
🤖 Prompt for AI Agents
.github/workflows/claude_pr_review.yml around lines 16-18: the checkout step
currently does a shallow checkout of the default branch and doesn't fetch the PR
head; update the checkout action to explicitly check out the PR head ref and
fetch full history by setting with: ref: ${{ github.event.pull_request.head.sha
}} (or head.ref) and fetch-depth: 0 so the workflow sees the PR changes and has
sufficient git history/context.

Comment on lines +33 to +49
- name: Configure Claude Code MCP
shell: bash
run: |
mkdir -p .claude
cat > .claude/settings.json << 'MCPEOF'
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
MCPEOF
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use environment variable for token; validate and escape inputs.

Embedding the token directly in shell script risks leaks. Use environment variables and validate/escape all inputs before passing to shell, especially for settings.json which will be loaded by Claude.

Apply this diff to use env var and remove direct token interpolation:

       - name: Configure Claude Code MCP
         shell: bash
+        env:
+          GITHUB_TOKEN_VAR: ${{ secrets.DENOBOT_PAT }}
         run: |
           mkdir -p .claude
           cat > .claude/settings.json << 'MCPEOF'
           {
             "mcpServers": {
               "github": {
                 "command": "npx",
                 "args": ["-y", "@modelcontextprotocol/server-github"],
                 "env": {
-                  "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
+                  "GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_TOKEN_VAR"
                 }
               }
             }
           }
           MCPEOF

Note: Use heredoc 'MCPEOF' (which you already do) to prevent variable expansion, then reference the env var using $GITHUB_TOKEN_VAR.

📝 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.

Suggested change
- name: Configure Claude Code MCP
shell: bash
run: |
mkdir -p .claude
cat > .claude/settings.json << 'MCPEOF'
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
MCPEOF
- name: Configure Claude Code MCP
shell: bash
env:
GITHUB_TOKEN_VAR: ${{ secrets.DENOBOT_PAT }}
run: |
mkdir -p .claude
cat > .claude/settings.json << "MCPEOF"
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_TOKEN_VAR"
}
}
}
}
MCPEOF
🤖 Prompt for AI Agents
.github/workflows/claude_pr_review.yml lines 33-49: the workflow currently
interpolates ${GITHUB_TOKEN} directly into the generated .claude/settings.json
which can leak secrets and allows unvalidated input; instead stop expanding the
token in the heredoc, write the token field to reference an environment variable
(e.g. GITHUB_TOKEN_VAR) so the runner injects it at runtime, ensure the heredoc
remains single-quoted to prevent expansion, and add a pre-check step that
validates the env var is set and escapes any characters before writing JSON
(fail the job with a clear error if the variable is missing or contains
disallowed content).

Comment on lines +51 to +69
- name: Create prompt file
shell: bash
run: |
cat > /tmp/prompt.txt << 'EOF'
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}

Please review this pull request with a focus on:
- Code quality and best practices
- Potential bugs or issues
- Security implications
- Performance considerations

Note: The PR branch is already checked out in the current working directory.

Use `gh pr comment` for top-level feedback.
Use `mcp__github__add_comment_to_pending_review` to add inline comments on specific lines of code.
Only post GitHub comments - don't submit review text as messages.
EOF
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Use environment variables for GitHub context to improve input validation.

GitHub context variables like ${{ github.repository }} are interpolated by the Actions runner before shell execution, which bypasses normal shell escaping. For better control and consistency with input validation, pass these via environment variables.

Apply this diff:

       - name: Create prompt file
         shell: bash
+        env:
+          REPO: ${{ github.repository }}
+          PR_NUMBER: ${{ github.event.pull_request.number }}
         run: |
           cat > /tmp/prompt.txt << 'EOF'
-          REPO: ${{ github.repository }}
-          PR NUMBER: ${{ github.event.pull_request.number }}
+          REPO: $REPO
+          PR NUMBER: $PR_NUMBER
           
           Please review this pull request with a focus on:
           - Code quality and best practices
           - Potential bugs or issues
           - Security implications
           - Performance considerations
           
           Note: The PR branch is already checked out in the current working directory.
           
           Use `gh pr comment` for top-level feedback.
           Use `mcp__github__add_comment_to_pending_review` to add inline comments on specific lines of code.
           Only post GitHub comments - don't submit review text as messages.
           EOF


---

🌐 Web query:

```web
GitHub Actions when are expressions ${{ }} evaluated relative to bash script execution

💡 Result:

Short answer

  • All GitHub Actions expressions ${ { ... } } are evaluated by the Actions engine before the shell executes your run script — they are expanded into literal text that the runner then executes. [1][2]

Key details

  • Job-level expressions/ifs are evaluated before the job is dispatched (server-side), so they can decide whether a job is created at all. [2]
  • Step-level expressions/ifs are evaluated by the runner before that step runs; the result is substituted into the step (including the run: body) and then the shell executes the substituted text. This is why using ${ { } } directly inside run: can lead to command/script injection if the expression contains uncontrolled input. [1][2][3]
  • Best practice: put values into env: via ${ { ... } } and reference them from the shell (e.g., echo "$VAR") instead of directly embedding ${ { ... } } inside run:. [3]

References
[1] GitHub Actions — Evaluate expressions in workflows and actions.
[2] GitHub Actions — Workflow syntax (job/step if evaluation notes).
[3] GitHub Blog — recommendation: don’t use ${ { } } in run sections (use env variables instead).


Remove the "major issue" severity; the code is safe but the env variable approach is cleaner per GitHub best practices.

The ${{ }} expressions are evaluated by the Actions runner before the shell script executes, and the best practice is to pass values via env variables and reference them from the shell. Your original code using a single-quoted heredoc is safe (values are written literally to the file), but the suggested refactor aligns with GitHub's documented approach for better maintainability. Apply the diff as originally proposed—it's a valid improvement, not a critical fix.

🤖 Prompt for AI Agents
.github/workflows/claude_pr_review.yml lines 51-69: replace direct GitHub
expression interpolation inside the heredoc with environment variables and
reference those in the shell; add env: REPO: ${{ github.repository }} and
PR_NUMBER: ${{ github.event.pull_request.number }} to the step, then in the run
block write the heredoc using unquoted EOF and include REPO: $REPO and PR
NUMBER: $PR_NUMBER so the runner injects values at runtime via the environment
rather than pre-evaluating the expressions.

Comment on lines +71 to +78
- name: Run Claude Code Review
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.DENOBOT_PAT }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude --print "$(cat /tmp/prompt.txt)" \
--allowedTools "mcp__github__add_comment_to_pending_review,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add concurrency control, error handling, and tighten tool permissions.

Without concurrency control, rapid PR updates cause conflicting reviews. Missing error handling means failures go silent. Tool permissions are too permissive (Bash(gh pr comment:*) allows any gh command).

Apply these diffs:

  1. Add concurrency to the job block (after permissions:):
     permissions:
       contents: read
       pull-requests: write
       id-token: write
+    concurrency:
+      group: claude-review-${{ github.event.pull_request.number }}
+      cancel-in-progress: true
  1. Add per-step timeouts and error handling (add before the Claude step):
       - name: Run Claude Code Review
+        timeout-minutes: 45
         shell: bash
         env:
           GITHUB_TOKEN: ${{ secrets.DENOBOT_PAT }}
           ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
         run: |
           claude --print "$(cat /tmp/prompt.txt)" \
-            --allowedTools "mcp__github__add_comment_to_pending_review,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
+            --allowedTools "mcp__github__add_comment_to_pending_review,Bash(gh pr diff),Bash(gh pr view)"
+
+      - name: Notify on failure
+        if: failure()
+        shell: bash
+        env:
+          GITHUB_TOKEN: ${{ secrets.DENOBOT_PAT }}
+        run: |
+          gh pr comment ${{ github.event.pull_request.number }} \
+            --body "⚠️ Claude PR review failed. Please check workflow logs."

Note: Removed wildcards from gh commands (e.g., gh pr comment:* → just review with diff/view, comment only via MCP tool). This prevents the Claude session from running arbitrary gh commands.

Committable suggestion skipped: line range outside the PR's diff.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants