permissions.ask rules are loaded and displayed in /permissions but never enforced (2.1.219, macOS)

Status Open
Reported on v2.1.219
Maintainer reply None cached
Activity 0 comments · opened Jul 25, 2026

AT-6: permissions.ask rules are loaded and displayed but never enforced

Product: Claude Code (CLI), version 2.1.219
Platform: macOS (darwin 25.5.0)
Urgency: 🔴 HIGH
Status: FILED 2026-07-25 via in-session /bug. Feedback ID 91e4a7c1-a77a-4a22-98db-94838f465918
Discovered: 2026-07-25

---

Summary

Permission rules in the ask tier are parsed, loaded, and shown in the /permissions UI under the heading "Claude Code will always ask for confirmation before using these tools." They never produce a confirmation prompt. Matching commands execute silently.

deny rules in the same file, added in the same edit, in the same session, work correctly. So does a PreToolUse hook exiting 2. The failure is specific to the ask tier, and it fails silently: no error, no warning, no log line.

A second, independent route to the same tier fails identically: a PreToolUse hook returning {"hookSpecificOutput": {"permissionDecision": "ask"}} also produces no prompt.

Why this is HIGH rather than MEDIUM

A permission control that silently enforces nothing is worse than an absent one. The configuration reads as protection, the product's own UI confirms it is active, and the operator reasonably believes commands are gated when they are not.

In our case the affected rules were the entire enforcement mechanism for two commitments of a governance decision covering destructive local execution: recursive deletion, database-destroying tasks, production database consoles, remote shells, and inline interpreter invocation (python3 -c, ruby -e). All were configured to prompt. None did. We discovered this only because we tested our own controls rather than trusting them.

Reproduction

Minimal, using only synthetic commands.

  1. In a project .claude/settings.json:
{
  "permissions": {
    "deny": ["Bash(echo DENYPROBE)"],
    "ask":  ["Bash(echo ASKPROBE)"]
  }
}
  1. In a session with permission_mode = default, ask Claude to run echo DENYPROBE.

Observed: blocked. Correct.

  1. Ask Claude to run echo ASKPROBE.

Observed: executes immediately, no prompt.
Expected: a confirmation prompt.

  1. Run /permissions and select the Ask tab.

Observed: Bash(echo ASKPROBE) is listed, under the text "Claude Code will always ask for confirmation before using these tools."

The rule is loaded. The UI says it will always ask. It never asks.

Variants tested, all identical in outcome

| Variant | Result |
|---|---|
| Bash(ruby -e:*) (trailing-wildcard form) | no prompt |
| Bash(ruby -e *) (space form) | no prompt |
| Bash(echo ASKPROBE) (bare literal, no wildcard) | no prompt |
| PreToolUse hook returning permissionDecision: "ask" | no prompt |
| Equivalent deny rule, bare literal | blocks correctly |

Ruled out

Each of these was tested, not assumed.

  • Reload / restart. Permission rules hot-reload: a deny rule added mid-session took effect immediately without a restart.
  • Rule syntax. Three forms failed identically, including a bare literal with no wildcard at all.
  • Cached session approval. ruby -e had never been approved in the session and appeared in no allowlist.
  • A conflicting allow rule. Every allowlist entry matching these commands is an exact literal (ruby -v, python3 -c "import PIL; print('PIL ok')"), none of which matches the probes. Documented behaviour is in any case that a matching ask rule prompts even when a more specific allow rule matches.
  • Hook ordering. The ask-returning hook was inert both first and last in the PreToolUse array.
  • A broken probe. The hook script emitted correct hookSpecificOutput JSON when run standalone.
  • Permissive configuration. permission_mode reported as default by the hook payload. defaultMode unset at user, project, and local scope. No blanket Bash allow at any scope.
  • A suspicious Bash(:) allow entry. Removing it changed nothing.

Environment

  • Claude Code 2.1.219, macOS
  • Rules in project-scope .claude/settings.json
  • permission_mode: default
  • Sandboxing: not enabled

Documentation note (separate, lower urgency)

The permissions documentation contains no JSON example of an ask array. The tier appears in prose describing evaluation order ("deny, then ask, then allow") and once in a configuration table (allowManagedPermissionRulesOnly, which states that setting prevents user and project settings from defining allow, ask, or deny rules, implying all three are settable). There is no worked example of the syntax anywhere. This made the feature difficult to validate and contributed to a long misdiagnosis. Suggest filing separately as a docs issue.

What we would find most useful in a response

Confirmation of whether permissions.ask in settings.json is expected to be enforced in 2.1.219, or whether the tier is currently UI-only. If the latter, the /permissions Ask tab text is misleading and should say so.

View original on GitHub ↗