[FEATURE] Support regex patterns in permission rules

Resolved 💬 4 comments Opened Mar 22, 2026 by CoonCat21 Closed May 1, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Permission rules currently use glob-style matching with * as the only wildcard. This makes it impossible to write reliable deny/allow rules for commands with combined short flags, equals-syntax arguments, or flag variants.

Combined short flags are invisible to glob patterns. Bash(sed *-i *) doesn't match sed -ni, sed -ie, or sed -i.bak because the -i is merged into a combined flag string. Glob has no way to express "any flag string containing the character i." The same problem affects rm -rf (vs -r, -Rf, -fr), git clean -fd (vs -f, -fx, -fxd), and many other commands.

Equals-syntax bypasses space-dependent patterns. Bash(gh api *--field *) expects a space after --field, so --field=value bypasses the deny rule entirely. Same for --input=, -f=, and any flag that accepts = syntax.

No character classes or alternation. Each flag variant requires its own rule. Denying sed in-place editing currently requires enumerating every permutation (-i, --in-place, -ni, -in, -ie, -i.bak, etc.) as separate rules.

The result is that permission deny rules are unreliable for any command with nontrivial flag syntax, which is most of them.

Proposed Solution

Allow permission patterns to optionally use regex syntax via a /pattern/ delimiter:

{
  "permissions": {
    "deny": [
      "Bash(/sed\\s+.*-[^\\s]*i/)",
      "Bash(/git\\s+push\\s+.*--force(-with-lease)?/)",
      "Bash(/rm\\s+.*-[^\\s]*[rR]/)",
      "Bash(/git\\s+clean\\s+.*-[^\\s]*f/)"
    ]
  }
}

Existing glob patterns (Bash(git status *)) would continue to work unchanged. Regex would be opt-in, detected by the / delimiters. This is a nonbreaking, additive change.

Alternative Solutions

The current workaround is writing PreToolUse hooks with custom regex logic (as demonstrated in #36900). This works but pushes platform-level complexity onto individual users for what should be a built-in capability.

More ambitious alternatives for the future include a flag-aware command tokenizer that decomposes combined short flags and normalizes --flag=value vs --flag value, or full shell AST parsing to handle compound commands. Both would be complementary to regex support but are larger in scope.

Priority

High - Significant impact on productivity

Feature Category

Configuration and settings

Use Case Example

  1. I'm configuring permissions for a Python/Node/Docker project using Claude Code
  2. I want to deny destructive operations like rm -r, sed -i, git push --force, git clean -f
  3. I write deny rules using glob patterns: Bash(sed *-i *), Bash(rm *-r *)
  4. Claude runs sed -ni '/pattern/p' file — the -i is buried in -ni, the glob doesn't match, and the file is silently modified in-place
  5. With regex support, I'd write Bash(/sed\s+.*-[^\s]*i/) which correctly matches any flag combination containing i, regardless of position or adjacent flags

Additional Context

Related issues that stem from the same root cause (glob-only matching):

  • #36637 — Chained bash commands bypass permission allowlists (only first segment evaluated)
  • #36900 — Inserted flags break glob patterns; user workaround uses PreToolUse hook with regex
  • #33692 — Regex in awk commands misinterpreted as file paths
  • #37391 — Legitimate shell escaping (\;, \|) triggers false positives
  • #37471 — Allowlist-only manifest proposal (complementary architectural change)
  • #36332 — More expressive argument patterns in hook matchers

View original on GitHub ↗

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