[FEATURE] Support regex patterns in permission rules
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
- I'm configuring permissions for a Python/Node/Docker project using Claude Code
- I want to deny destructive operations like
rm -r,sed -i,git push --force,git clean -f - I write deny rules using glob patterns:
Bash(sed *-i *),Bash(rm *-r *) - Claude runs
sed -ni '/pattern/p' file— the-iis buried in-ni, the glob doesn't match, and the file is silently modified in-place - With regex support, I'd write
Bash(/sed\s+.*-[^\s]*i/)which correctly matches any flag combination containingi, 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
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗