Deny rules are bypassable via flag reordering (e.g. git -C) — need finer pattern matching

Resolved 💬 3 comments Opened Feb 12, 2026 by adriangalilea Closed Feb 12, 2026

The bug

Permission patterns use prefix matching. Deny rules are trivially bypassed by reordering flags.

Bash(git reset --hard:*) blocks git reset --hard but not git -C /path reset --hard. Same command. The -C flag just changes the working directory.

Broadening with Bash(git -C:*) breaks deny rules: git -C /path add -A sails through because Bash(git add -A:*) doesn't match commands starting with git -C.

The documented * syntax that would allow mid-pattern wildcards doesn't work in settings.json (#24815). The :* syntax that does work only supports prefix matching.

Steps to reproduce

  1. Add Bash(git reset --hard:*) to deny rules in settings.json
  2. Have Claude execute git -C /some/path reset --hard
  3. The command runs without being denied

The feature request

The pattern system needs finer granularity. Right now there is no way to express "deny this subcommand regardless of flags." Some options:

  • Support mid-command wildcards (the * syntax that's documented but broken)
  • Regex support in patterns
  • Semantic matching that understands command structure (e.g. git subcommand extraction)

Related issues

  • #24815 — * syntax doesn't work in settings.json
  • #21642 — Official commit plugin missing required git commands in allowed-tools
  • #14956 — Skill allowed-tools doesn't grant Bash permission

Workaround

I wrote a PreToolUse hook in Go that parses the actual command string, strips global flags, and enforces deny/ask rules on the normalized subcommand. Writeup and source: https://adriangalilea.com/claude-code-permission-bypass

Environment

  • Claude Code 2.1.38
  • macOS
  • Anthropic API

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗