Deny rules for Read tool not enforced when broad allow rule exists

Resolved 💬 3 comments Opened Jan 19, 2026 by panoptican Closed Jan 19, 2026

Description

Deny rules in permissions.deny for the Read tool are not being enforced when a broad Read(**) allow rule exists in permissions.allow.

Steps to Reproduce

  1. Add the following to ~/.claude/settings.json:
{
  "permissions": {
    "allow": [
      "Read(**)"
    ],
    "deny": [
      "Read(**/.secrets*)"
    ]
  }
}
  1. Create a file ~/.secrets with some content
  2. Start a new Claude Code session
  3. Ask Claude to read ~/.secrets

Expected Behavior

The Read tool should be blocked with a permission denied error, since **/.secrets* matches the path ~/.secrets (expands to /Users/<username>/.secrets).

Deny rules should take precedence over allow rules for matching paths.

Actual Behavior

The Read tool successfully reads the file contents. The deny rule is completely ignored.

Environment

  • OS: macOS (Darwin 24.6.0)
  • Claude Code version: Latest as of 2025-01-19

Additional Context

This is a security concern as users may believe sensitive files are protected by deny rules when they are not. The deny list included patterns for:

  • .env files
  • .secrets files
  • .pem and .key files
  • credentials/ directories
  • .aws/ and .ssh/ directories

None of these protections are effective if a broad Read(**) allow rule exists.

Suggested Fix

Deny rules should always be evaluated and take precedence over allow rules, regardless of specificity or order in the lists.

View original on GitHub ↗

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