User deny permissions in settings.json ignored when command appears in allow list

Resolved 💬 3 comments Opened Dec 5, 2025 by CyberneticNomad-v808 Closed Dec 8, 2025

Claude Code Bug Report: User Deny Permissions Ignored

Summary

User-defined deny permissions in ~/.claude/settings.json are being ignored when the same commands appear in an allow list (either system-level or project-level).

Environment

  • OS: Pop!_OS 24.04 Cosmic (beta)
  • Claude Code Version: Current (as of 2025-12-04)
  • Model: claude-opus-4-5-20251101

Steps to Reproduce

  1. Add commands to deny list in ~/.claude/settings.json:

``json
{
"permissions": {
"deny": [
"Bash(cat:*)",
"Bash(grep:*)",
"Bash(pgrep:*)"
]
}
}
``

  1. Start Claude Code session
  1. Observe that Claude still executes Bash(cat:*) commands without user approval

Expected Behavior

User-defined deny permissions should take highest precedence and block the specified commands regardless of any other allow lists.

The permission hierarchy should be:

  1. User deny (highest - always blocks)
  2. User allow
  3. Project allow
  4. System defaults

Actual Behavior

The system prompt shows Bash(cat:*) in the "allowed without user approval" list despite being explicitly denied in user settings:

You can use the following tools without requiring user approval: Bash(docker logs:*), ... Bash(cat:*), ...

Claude then executes cat commands freely, ignoring the user's explicit deny.

Impact

  • Security: Users cannot reliably restrict Claude's access to sensitive commands
  • Trust: Users lose confidence that their security configurations are being respected
  • Data exposure: Commands the user explicitly wanted blocked can still execute

Evidence

User settings file (~/.claude/settings.json) contains:

"permissions": {
  "deny": [
    "Bash(cat:*)",
    "Bash(grep:*)",
    "Bash(pgrep:*)"
  ]
}

Yet Claude executed cat ~/.claude.json and similar commands without requesting permission.

Suggested Fix

In the permission resolution logic, check user deny list FIRST before allowing any command, regardless of other allow sources.

Pseudocode:

if command in user_deny_list:
    return DENIED  # Stop here, don't check allow lists
elif command in user_allow_list:
    return ALLOWED
elif command in project_allow_list:
    return ALLOWED
else:
    return PROMPT_USER

Workaround

None known. The deny list is simply ignored.

Reporter

Generated via Claude Code session on 2025-12-04

View original on GitHub ↗

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