Repository navigation
ci: allow git-CLI write commands for ssh_signing_key commit path - #236
Conversation
Setting ssh_signing_key switches the action's commit mechanism from the GitHub API (mcp__github_file_ops__commit_files) to the local git CLI, but the implement + fix allowlists only carried read-only git verbs (status/diff/log/show). The agent's commit and branch/push commands were denied, so run #10 on the dummy issue finished with no PR and no commit. Add the git-CLI write verbs the local-git commit path needs — checkout/switch/branch/add/commit/push/config — to both the implement and fix job allowlists. This is the same authority the agent already had via the file-ops MCP (commit + push to its own claude/* branch); only the mechanism changed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NVR5yWevceZEFbTJmpviiM
WalkthroughThis PR updates the ChangesClaude Workflow Allowlist Updates
Estimated code review effort: 1 (Trivial) | ~3 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Preview DeploymentPreview URL: https://2dd39bdc.bestax.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/claude-implement.yml:
- Line 109: The allowedTools list in claude-implement workflow is still too
broad because the git prefixes permit dangerous subcommands. Update the tool
policy around the allowedTools entry to narrow git usage by removing unnecessary
git config access and explicitly blocking unsafe subcommands through
--disallowedTools, especially any force-push, branch deletion/rename, and
config-write operations. Keep the existing git-related symbols in the workflow,
but tighten them so only the minimal safe git commands needed by
claude-code-action remain available.
In @.github/workflows/claude-pr-loop.yml:
- Line 345: The allowedTools list in the claude-pr-loop workflow is still too
broad for git operations. Tighten the entries for git in the prompt/tool
allowlist by removing or narrowing `git push`, `git branch`, and `git config` so
only the exact safe subcommands and flags needed by the workflow are permitted.
Update the allowlist near the `allowedTools` configuration to avoid granting
write-capable or destructive git access unless it is strictly required.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d4be84c4-735a-4112-b9f2-0c5ad5e2e34d
📒 Files selected for processing (2)
.github/workflows/claude-implement.yml.github/workflows/claude-pr-loop.yml
| --max-turns 150 | ||
| --model claude-sonnet-5 | ||
| --allowedTools "Bash(pnpm install:*),Bash(pnpm run:*),Bash(pnpm test:*),Bash(pnpm exec:*),Bash(pnpm --filter:*),Bash(pnpm ls:*),Bash(pnpm why:*),Bash(node:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(mkdir:*),Bash(gh issue view:*),Bash(gh issue comment:*),Bash(gh pr create:*),Bash(gh pr view:*),Bash(gh pr edit:*),Bash(gh pr diff:*),Bash(gh pr checks:*)" | ||
| --allowedTools "Bash(pnpm install:*),Bash(pnpm run:*),Bash(pnpm test:*),Bash(pnpm exec:*),Bash(pnpm --filter:*),Bash(pnpm ls:*),Bash(pnpm why:*),Bash(node:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(git checkout:*),Bash(git switch:*),Bash(git branch:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(git config:*),Bash(mkdir:*),Bash(gh issue view:*),Bash(gh issue comment:*),Bash(gh pr create:*),Bash(gh pr view:*),Bash(gh pr edit:*),Bash(gh pr diff:*),Bash(gh pr checks:*)" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does claude-code-action support a disallowedTools or deny-rule input alongside --allowedTools?
💡 Result:
Yes, claude-code-action supports the use of both --allowedTools and --disallowedTools [1][2]. You can pass these flags through the claude_args input in your GitHub Actions workflow configuration [1][2]. The claude_args parameter is designed to accept any valid Claude Code CLI arguments [1][2]. Example usage in a GitHub Action: - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} claude_args: "--allowedTools Read,Grep --disallowedTools Bash" Key behaviors for these tools include: - Both flags accept the same rule format, such as ToolName(specifier) [3]. - If both --allowedTools and --disallowedTools are set, --disallowedTools takes precedence; if a tool is listed in both, it is removed [3]. - Deny rules (via --disallowedTools) are restrictive and cannot be overridden by allow rules [4]. For example, a tool denied at any configuration level (including managed settings) cannot be re-allowed by the CLI flag [4].
Citations:
- 1: https://code.claude.com/docs/en/github-actions
- 2: https://code.claude.com/docs/en/github-actions.md
- 3: https://code.claude.com/docs/en/tools-reference
- 4: https://code.claude.com/docs/en/permissions
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the workflow around the referenced line
file=".github/workflows/claude-implement.yml"
wc -l "$file"
sed -n '1,220p' "$file" | cat -n
# Look for other git-related tool allowances or signs this flow needs write/config access
rg -n "git (push|config|branch|checkout|switch|add|commit|diff|status|show|log)" .github/workflows . -g '!**/node_modules/**' || trueRepository: allxsmith/bestax
Length of output: 14202
🌐 Web query:
claude-code-action disallowedTools precedence allowedTools deny rules git push git config CLI arguments
💡 Result:
In Claude Code, permission rules are evaluated in a strict order: deny, then ask, then allow [1][2]. A deny rule at any scope (user, project, or CLI) takes precedence and cannot be overridden by an allow rule at another scope or the same scope [1][2]. Regarding tool configuration and precedence: 1. Settings Precedence: Configuration follows a hierarchy where managed settings cannot be overridden, followed by CLI arguments (temporary session overrides), local project settings (.claude/settings.local.json), shared project settings (.claude/settings.json), and finally user settings (~/.claude/settings.json) [1][2]. 2. Deny Rules: A broader deny rule (e.g., Bash(aws *)) blocks all matching calls, including those that might otherwise be matched by a narrower allow rule [1][2]. 3. AllowedTools vs. DisallowedTools: - --allowedTools (whitelist) pre-approves tools. If a tool is not in the allowlist, it falls through to the configured permission mode [3]. - --disallowedTools (blacklist) removes tool definitions from the request entirely, meaning Claude cannot see or attempt them [3]. Disallowed tools cannot be re-enabled by allow rules [1][2]. 4. Git Push and CLI Arguments: - Claude Code contains an undocumented, harness-level safety guard that blocks assistant-initiated git push to the default branch [4]. This guard acts independently of standard permission rules, meaning it can fire even if Bash(git push *) is explicitly allowed in settings [4]. - CLI arguments like --allowedTools, --disallowedTools, and --permission-mode provide temporary overrides for the current session [1][5]. Note that --allowedTools may appear to be ignored if using --permission-mode bypassPermissions, as the latter bypasses standard permission checks [6]. To manage Git or other sensitive operations, it is recommended to use specific deny rules to refine broader allow rules (e.g., allowing Bash(git *) while denying Bash(git push --force *)) [7]. Since there is no documented opt-out for the default-branch push guard, it remains active by default [4].
Citations:
- 1: https://code.claude.com/docs/en/permissions
- 2: https://code.claude.com/docs/en/permissions.md
- 3: https://code.claude.com/docs/en/agent-sdk/permissions.md
- 4: Feature Request: Documented opt-out for built-in default-branch push guard (CLI) anthropics/claude-code#52001
- 5: https://www.developersdigest.tech/blog/claude-code-permissions-settings-guide
- 6: Is --allowedTools with --permission-mode bypassPermissions behavior expected? anthropics/claude-code#12232
- 7: https://www.iamraghuveer.com/posts/claude-code-project-scoped-permissions/
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Lightweight read-only check for the Claude Code Action docs via web lookup is not available in-shell,
# so inspect repository references only.
rg -n "claude-implement|claude_args|allowedTools|disallowedTools|ssh_signing_key|git config" .github README* docs* . -g '!**/node_modules/**' || trueRepository: allxsmith/bestax
Length of output: 2871
Narrow the git tool permissions. Bash(git push:*), Bash(git branch:*), and Bash(git config:*) are prefix-based, so this still allows force-pushes, branch deletion/renames, and arbitrary config writes. claude-code-action supports --disallowedTools, so deny the dangerous subcommands explicitly and drop git config if this flow doesn’t need it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/claude-implement.yml at line 109, The allowedTools list in
claude-implement workflow is still too broad because the git prefixes permit
dangerous subcommands. Update the tool policy around the allowedTools entry to
narrow git usage by removing unnecessary git config access and explicitly
blocking unsafe subcommands through --disallowedTools, especially any
force-push, branch deletion/rename, and config-write operations. Keep the
existing git-related symbols in the workflow, but tighten them so only the
minimal safe git commands needed by claude-code-action remain available.
| --max-turns 80 | ||
| --model claude-sonnet-5 | ||
| --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(pnpm install:*),Bash(pnpm run:*),Bash(pnpm test:*),Bash(pnpm exec:*),Bash(pnpm --filter:*),Bash(node:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr checks:*),Bash(gh pr comment:*),Bash(gh api:*)" | ||
| --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(pnpm install:*),Bash(pnpm run:*),Bash(pnpm test:*),Bash(pnpm exec:*),Bash(pnpm --filter:*),Bash(node:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(git checkout:*),Bash(git switch:*),Bash(git branch:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(git config:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr checks:*),Bash(gh pr comment:*),Bash(gh api:*)" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the workflow files and nearby references.
git ls-files '.github/workflows/*' | sed -n '1,120p'
echo '--- claude-pr-loop.yml matches ---'
rg -n 'allowedTools|git push|git config|git branch|UNTRUSTED DATA|never push to main|main' .github/workflows/claude-pr-loop.yml
echo '--- claude-implement.yml matches ---'
rg -n 'allowedTools|git push|git config|git branch|UNTRUSTED DATA|never push to main|main' .github/workflows/claude-implement.yml
echo '--- surrounding context in claude-pr-loop.yml ---'
sed -n '300,380p' .github/workflows/claude-pr-loop.yml
echo '--- surrounding context in claude-implement.yml ---'
sed -n '300,380p' .github/workflows/claude-implement.ymlRepository: allxsmith/bestax
Length of output: 7150
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- claude-implement.yml around the allowlist ---'
sed -n '90,190p' .github/workflows/claude-implement.yml
echo '--- claude-pr-loop.yml around the allowlist ---'
sed -n '330,380p' .github/workflows/claude-pr-loop.ymlRepository: allxsmith/bestax
Length of output: 10182
Tighten the git allowlist in .github/workflows/claude-pr-loop.yml:345
Bash(git push:*) and Bash(git branch:*) still allow destructive flags like --force, delete, and rename, and Bash(git config:*) grants arbitrary repo-local config writes. The prompt text is not an enforcement boundary, so narrow these to the exact subcommands/flags needed or drop the write-capable git tools if they aren’t required.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/claude-pr-loop.yml at line 345, The allowedTools list in
the claude-pr-loop workflow is still too broad for git operations. Tighten the
entries for git in the prompt/tool allowlist by removing or narrowing `git
push`, `git branch`, and `git config` so only the exact safe subcommands and
flags needed by the workflow are permitted. Update the allowlist near the
`allowedTools` configuration to avoid granting write-capable or destructive git
access unless it is strictly required.
|
🎉 This PR is included in version 5.2.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 3.2.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
What
Adds the git-CLI write verbs —
checkout/switch/branch/add/commit/push/config— to the--allowedToolsof both the implement job (claude-implement.yml) and the fix job (claude-pr-loop.yml).Why
Setting
ssh_signing_key(added in #234, so bestaxbot's commits are Verified for branch protection) switches the action's commit mechanism from the GitHub API (mcp__github_file_ops__commit_files) to the local git CLI. But both allowlists only carried read-only git verbs (status/diff/log/show).Result on the dummy validation run (#10, issue #235): the agent's
git commit/git branch/git pushcalls were all denied, so the run finished green but produced no commit and no PR — bestaxbot's own comment reported the denials.This restores the commit path. It is not new authority: the agent already had commit + push to its own
claude/*branch via the file-ops MCP;ssh_signing_keyonly changed the mechanism to local git.Scope
Two one-line allowlist edits. No prompt, permission, or logic changes. The fix prompt already instructs "Commit … and push to BRANCH", which is git-CLI native.
Testing
claude-fixvalidation and confirm bestaxbot's commit shows Verified and a PR is opened.Generated by Claude Code
Summary by CodeRabbit