[BUG] Claude is ignoring `allow` permissions in global `settings.json`

Open 💬 27 comments Opened Jan 14, 2026 by mieubrisse

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

The Bash permission pattern Bash(ls *) in settings.json is not matching the command ls -la ~/.claude/, requiring user approval despite the pattern being in the allow list.

When Claude attempts to execute ls -la ~/.claude/, the user is prompted for permission even though Bash(ls *) is explicitly configured in the permissions.allow array.

What Should Happen?

The command ls -la ~/.claude/ should be automatically allowed without requiring user approval, as it should match the pattern Bash(ls *) which is intended to allow any ls command with any arguments.

Error Messages/Logs

No error messages - the command simply requires manual approval instead of being auto-approved by the permission pattern.

Steps to Reproduce

  1. Add Bash(ls *) to the permissions.allow array in ~/.claude/settings.json:

``json
{
"permissions": {
"allow": [
"Bash(ls *)"
]
}
}
``

  1. Start a Claude Code session
  2. Request Claude to execute ls -la ~/.claude/
  3. Observe that Claude prompts for permission approval

Expected: Command executes without permission prompt
Actual: User is prompted to approve the command

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Claude Code Version

Latest (as of 2026-01-14)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Current settings.json configuration:

{
  "permissions": {
    "allow": [
      "Bash(grep *)",
      "Bash(ls *)",
      "Bash(pwd *)",
      "Bash(mkdir *)",
      ...
    ]
  }
}

Settings file location: ~/.claude/settings.json (symlinked to ~/app/dotfiles/claude/settings.json)

System info:

  • OS Version: Darwin 24.4.0
  • Platform: darwin

Hypotheses about the issue:

  1. Tilde expansion timing: The pattern may be evaluated before shell tilde (~) expansion occurs, causing the literal string ~/.claude/ not to match the expected pattern
  2. Wildcard matching edge case: The wildcard * in Bash(ls *) may not properly handle certain combinations of flags and path arguments
  3. Pattern precedence or parsing: There may be an issue with how the command string is parsed before pattern matching

Questions for clarification:

  1. Is Bash(ls *) expected to match ls -la ~/.claude/?
  2. What is the correct pattern syntax to allow all ls commands regardless of flags and paths?
  3. Should multiple patterns be required (e.g., both Bash(ls) and Bash(ls *), or Bash(ls:*))?
  4. Is there a known limitation with special characters (tilde, dots) in path arguments affecting pattern matching?

Related patterns that also exist in the allow list and work correctly:

  • Bash(grep *) - appears to work
  • Bash(pwd *) - appears to work
  • Bash(git status *) - appears to work

View original on GitHub ↗

27 Comments

mdbudnick · 6 months ago

I am having a similar issue. I would like Claude to run read and node project commands without asking for permission each time, but it is still asking for permission it has been granted. There's nothing in my hooks that would prevent this.

The project level .claude/settings.local.json is being respected, but should be allowed by the global settings.json permissions already.

{
  "permissions": {
    "allow": [
      "Bash(npm run convert:*)",
      "Bash(npm run build:*)",
      "Bash(node dist/test-runner.js:*)",
      "Bash(tee:*)"
    ]
  }
}

claude --version
2.1.7 (Claude Code)

Here are my global settings.json permissions (no, it was not trying to read the denied files). I have not tested them all, this is just to show my configuration:

 "permissions": {
    "deny": [
      "Read(.envrc)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(./config/credentials.json)",
      "Read(./build)",
      "Read(~/.aws/**)"
    ],
    "allow": [
      "Bash(npm run *)",
      "Bash(npm test*)",
      "Bash(npm install*)",
      "Bash(npm ci*)",
      "Bash(pnpm *)",
      "Bash(yarn *)",
      "Bash(npx *)",
      "Bash(gh pr *)",
      "Bash(gh issue *)",
      "Bash(gh repo view*)",
      "Bash(gh api *)",
      "Bash(gh run list*)",
      "Bash(gh run view *)",
      "Bash(gh run watch *)",
      "Bash(gh workflow *)",
      "Bash(git status*)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git branch*)",
      "Bash(git show*)",
      "Bash(git fetch*)",
      "Bash(git remote*)",
      "Bash(git rev-parse*)",
      "Bash(git ls-files*)",
      "Bash(ls *)",
      "Bash(ls)",
      "Bash(cat *)",
      "Bash(head *)",
      "Bash(tail *)",
      "Bash(wc *)",
      "Bash(file *)",
      "Bash(which *)",
      "Bash(pwd)",
      "Bash(tsc *)",
      "Bash(tsc)",
      "Bash(eslint *)",
      "Bash(prettier *)",
      "Bash(jest *)",
      "Bash(vitest *)",
      "Bash(node *)",
      "Glob","Bash(node *)",
      "Grep",
      "Read",
      "WebFetch",
      "WebSearch"
    ]
  },
mieubrisse · 6 months ago

Now it's ignoring it for mkdir.

In my global ~/.claude/settings.json:

{
  "permissions": {
    "allow": [
      "Bash(mkdir *)",

I asked Claude to create a project-specific .claude/settings.json in the repo, and got:

 Bash command

   mkdir -p /Users/odyssey/code/prompt-generator/.claude
   Create .claude directory

 Do you want to proceed?
 ❯ 1. Yes
   2. Yes, and always allow access to prompt-generator/ from this project
   3. No
mieubrisse · 6 months ago

Would be great to get someone from Anthropic to explain why it's just not working

mdbudnick · 6 months ago

Issues with permissions are pretty critical.

lucasmccomb · 6 months ago

Would love a fix for this :)

richardkmichael · 5 months ago

I'm seeing this too, Claude 2.1.12 (npm).

Suspiciously, in the permission prompt choice 2: /tmp has become tmp/. This is what /tmp means in the settings permission "notation" (whereas actual /tmp would be: //tmp). I asked Claude: List files in /tmp.

 $ cat .claude/settings.local.json
{
  "permissions": {
    "allow": [
      "Bash(ls:*)"
    ]
  }
}

But being prompted:

⏺ Bash(ls /tmp/tts_notify_*)
  ⎿  Running…

 Bash command

   ls /tmp/tts_notify_*
   List TTS notify temp files

 Do you want to proceed?
 ❯ 1. Yes
   2. Yes, allow reading from tmp/ from this project
   3. No

 Esc to cancel · Tab to add additional instructions
janderland · 5 months ago

I'm having the same issues when trying to allow running the miniserve binary:

 {
    "permissions": {
      "allow": [
        "Bash(miniserve:*)"
      ]
    }
  }

Added to both the project and global config, but Claude always asks for permission.

jspiro · 5 months ago

This is utterly maddening. I want every single Claude session I start to have the same basic set of rules, so I don't have to start from scratch every time. If only they had some kind of artificial intelligence that could read literally every single GitHub issue and start writing a fix for it, given that supposedly they do 90% of their internal development using the tool itself...

jspiro · 5 months ago

It's also a massive productivity killer because I think I am leaving it alone to work, and then three seconds after I get up, it asks something stupid like, "Am I allowed to use ls on a directory?" Even though I already have approved it globally.

mdbudnick · 5 months ago

If and when the AI apocalypse happens, I'm going to point to this issue.

ibash · 5 months ago

Huh, the issue I opened was marked as a duplicate, but I have the opposite problem. Claude was doing things without my approval and without my permission.

rythazhur · 4 months ago

Still broken.

trungbui2000 · 4 months ago

Another data point for this issue.

Setup:

  • ~/.claude/settings.json (global) contains:

```json
{
"permissions": {
"allow": [
"Bash(ls:*)",
]
}
}

  • Running ls ~/src/.claude/still prompts for permission.

Environment:

  • Claude Code 2.1.52
  • macOS Darwin 24.6.0
  • Shell: zsh
Kasper-UBI · 4 months ago

I am experiencing an issue with allow permission for gh issue comment.

Setup 1:
~/.claude/settings.json (global) contains:

  • Bash(gh issue comment*)

Permission prompt does appear when executing:

bash(gh issue comment $NUMBER --repo $REPO --body "$(cat <<'EOF'                                                                                                                                                                                                                                                                 
   Imagine                                                                                                                                                                                                                                                                                                                     
   long
   multiline
   text
   here
EOF
)")

Setup 2:
~/.claude/settings.json (global) contains:

  • `Bash(gh issue comment*)
  • Write`

Permission prompt doesn't appear when executing:

  1. Write(/tmp/gh-comment-body.md)
  2. Bash(gh issue comment $NUMBER --repo $REPO --body-file /tmp/gh-comment-body.md 2>&1)

Environment:

  • Claude Code 2.1.56
  • Opus 4.6
  • Ubuntu 24.04.3 LTS Terminal on windows 11 with WSL 2.6.1.0
nmnewnham · 4 months ago

still broken, even simple read commands that have been added to settings, are being prompted upon every command

HyoilKim · 4 months ago

➕ 1

yarpskendaya · 4 months ago

Still broken, it's unworkable to have to accept any read operation

Vedinsoh · 4 months ago

Still an issue, no matter if I work in CLI, desktop app or VS Code extension same problem.

jarfa · 4 months ago
quinnpowell · 4 months ago

Broken for me too and makes using CC a nightmare, or I am forced to bypass all permissions to keep my sanity.

omujahid-namaa · 3 months ago

Still broken.

joaovcoliveira · 3 months ago

Had similar issues with allow rules being ignored. I built a tool that combines hooks (PreToolUse + PermissionRequest) with allow rules as a belt-and-suspenders approach — if one layer misses, the other catches it. npx claude-trust-me-bro enable to try it. https://github.com/joaovcoliveira/claude-trust-me-bro (I'm the author)

JasonStewart-AR · 3 months ago

For others who come along - I've added a hook call to check aws commands and pre-authorize any I recognize as non-destructive. Useful for others I hope:

  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.command' | grep -qE '^aws (dynamodb (query|scan|describe-table|list-tables|get-item|batch-get-item)|ecs (describe-services|describe-tasks|list-tasks|list-services)|logs (tail|filter-log-events|describe-log-groups)|sqs get-queue-attributes|ssm start-session|sts get-caller-identity|sso login|secretsmanager get-secret-value|elbv2 describe-target-health|events (list-rules|list-targets-by-rule|describe-rule)) ' && echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\",\"permissionDecisionReason\":\"Auto-approved read-only AWS command\"}}' || echo '{}'",
            "timeout": 5
          }
        ]
      }
    ]
  },
ethanfischer · 3 months ago

Still an issue on 2.1.84

martingercke · 2 months ago

I also still see this with 2.1.114 on win11

gbodeen · 2 months ago

Still an issue in 2.1.119 on linux

wlinna · 2 months ago

This is still an issue with 2.1.126. I'm trying to allow Claude to run cargo check via distrobox like this:

"Bash(distrobox enter fedora -- cargo check *)",

I also tried to allow Claude to read example code from specific absolute path, but it every time asks for permission anyways. Thinks like this do not work

"Read(/home/xyz/test/lightyear/*)",

The same happens whether I use global or project configuration.

But every time Claude Code would ask permission. Permissions not working makes it impossible to let Claude Code do any independent work at all basically :(