Skip to content

chore(perms): allow git push, keep blocking force pushes#202

Merged
bestdan merged 3 commits into
mainfrom
bestdan/relax-git-push-perms
Jun 18, 2026
Merged

chore(perms): allow git push, keep blocking force pushes#202
bestdan merged 3 commits into
mainfrom
bestdan/relax-git-push-perms

Conversation

@bestdan

@bestdan bestdan commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

Narrows the git-push permission rules in .claude/settings.json so Claude Code can push feature branches, while history-rewriting pushes stay hard-denied.

Before:

"deny": [
  "Bash(git push:*)",        // blocked ALL pushes
  "Bash(git push --force:*)"
]

After:

"deny": [
  "Bash(git push --force:*)",
  "Bash(git push -f:*)"
]

Why

The blanket Bash(git push:*) deny is a hard block (not overridable via the permission prompt), so the agent couldn't push any branch — every push had to be run manually. Force pushes remain blocked to protect branch history, and server-side branch protection on main is unchanged as the backstop. npm publish / pnpm publish / rm -rf denies are untouched.

Replace the blanket git push deny with force-push-only denies so feature
branches can be pushed while history rewrites stay blocked.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request modifies the deny list in .claude/settings.json to replace the broad git push block with a specific block for git push -f. However, the review feedback highlights a critical security bypass: because of how Claude Code parses commands, the proposed patterns will fail to match and block force pushes. Additionally, naive wildcard matching for -f could accidentally block common branch names containing -f. A more robust set of patterns is suggested to safely and effectively block force pushes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread .claude/settings.json Outdated
Comment on lines +36 to +37
"Bash(git push --force:*)",
"Bash(git push -f:*)",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-critical critical

⚠️ Critical Security Bypass & Usability Issue

The current patterns will fail to block force pushes and could also block normal pushes if implemented incorrectly.

1. Why the current patterns fail (Security Bypass)

Claude Code's permission system parses commands into a command/subcommand part (before the colon :) and an arguments part (after the colon :).

  • For any git push command (e.g., git push --force or git push origin main -f), the command part is parsed as git push.
  • Therefore, Claude Code will look for permission rules matching Bash(git push:<arguments>).
  • Because your patterns expect the command part itself to be git push --force or git push -f (before the colon), they will never match. This means all force pushes will be silently allowed without any block or prompt!

2. The danger of naive wildcard matching (Usability Issue)

If we try to fix this by simply using Bash(git push:*-f*), it will match any argument containing -f. This includes extremely common branch names like:

  • feature-flags
  • refactor-forms
  • add-fields
  • user-feedback

This would completely break the ability to push these branches, causing major frustration.

3. The Solution

To safely and comprehensively block force pushes without false positives, we must target the arguments of git push specifically:

  • Block --force and --force-with-lease anywhere in the arguments.
  • Block -f only when it is a standalone flag (at the start, middle, or end of the arguments, or as the sole argument).
      "Bash(git push:*--force*)",
      "Bash(git push:*--force-with-lease*)",
      "Bash(git push:-f)",
      "Bash(git push:-f *)",
      "Bash(git push:* -f)",
      "Bash(git push:* -f *)"

Copilot AI left a comment

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.

Pull request overview

Narrows the Claude Code permission denies in .claude/settings.json to allow non-force git push operations (e.g., pushing feature branches) while intending to keep history-rewriting pushes blocked.

Changes:

  • Removed the blanket deny rule for all git push invocations.
  • Kept/added deny rules targeting force pushes via --force and -f.

Comment thread .claude/settings.json Outdated
Comment on lines 35 to 39
"Bash(rm -rf:*)",
"Bash(git push:*)",
"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Bash(npm publish:*)",
"Bash(pnpm publish:*)"
bestdan added 2 commits June 18, 2026 15:53
The flag-adjacent deny patterns only matched when --force/-f
immediately followed 'push', so 'git push origin main --force' and
--force-with-lease slipped through. Use space-form wildcard patterns
(colons are literal mid-pattern per Claude Code permission matching)
to catch the flags anywhere without matching branch names like
feature-flags.
@bestdan bestdan merged commit c30591c into main Jun 18, 2026
7 checks passed
@bestdan bestdan deleted the bestdan/relax-git-push-perms branch June 18, 2026 20:03
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.

2 participants