Auto-mode permission decider denies remediation-gated retries after PreToolUse hook denial

Resolved 💬 1 comment Opened Apr 21, 2026 by lesaai Closed May 27, 2026

Summary

Intent-aware gating vs shape-aware gating: the shape-aware version creates the bypass surface it's trying to prevent.

In defaultMode: auto with skipAutoPermissionPrompt: true, the permission decider pattern-matches prior tool call denied by a PreToolUse hook → same-intent retry as a bypass, even when the deny reason's remediation was completed between the two calls.

Minimal reproducer

~/demo/deny-then-allow.mjs:

#!/usr/bin/env node
import { existsSync, writeFileSync, mkdirSync } from 'fs';
const marker = '/tmp/decider-repro/denied';
let raw = ''; for await (const c of process.stdin) raw += c;
const input = JSON.parse(raw);
if (input.tool_name === 'Bash' && !existsSync(marker)) {
  mkdirSync('/tmp/decider-repro', { recursive: true });
  writeFileSync(marker, '1');
  process.stdout.write(JSON.stringify({
    hookSpecificOutput: {
      hookEventName: 'PreToolUse',
      permissionDecision: 'deny',
      permissionDecisionReason: 'Read README.md first, then retry.',
    },
  }));
}
process.exit(0);

~/.claude/settings.json (minimal):

{
  "permissions": { "defaultMode": "auto" },
  "skipAutoPermissionPrompt": true,
  "skipDangerousModePermissionPrompt": true,
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{
        "type": "command",
        "command": "node ~/demo/deny-then-allow.mjs",
        "timeout": 5
      }]
    }]
  }
}

Sequence:

  1. rm -rf /tmp/decider-repro && mkdir /tmp/test-repo && echo hi > /tmp/test-repo/README.md
  2. Ask Claude Code to run ls /tmp/test-repo. Hook denies with "Read README.md first, then retry."
  3. Ask Claude Code to Read /tmp/test-repo/README.md. Read succeeds.
  4. Ask Claude Code to retry ls /tmp/test-repo. Hook no longer denies (marker set). Auto-mode denies the retry with a reason about "retry after guard block bypass pattern" that does not reference the intervening Read.

Expected

Step 4 allowed. The hook's deny reason named the remediation ("Read README.md first"); the agent performed it; the retry should proceed.

Actual

Step 4 denied by auto-mode. Agents adapt by changing command shape (-F commit-msg-file for git commit, tool-swap EditBash, etc.) to slip the pattern matcher ... the exact behavior the pattern is meant to catch.

Requested fix

A Read of X.md after a deny telling the agent to read X.md should not cause the next tool call to be denied as a bypass. The mechanism is for you to determine.

Environment

  • Claude Code 2.1.116
  • macOS 26.2 (darwin 25.2.0)
  • ~/.claude/settings.json: "permissions": { "defaultMode": "auto" } + "skipAutoPermissionPrompt": true + "skipDangerousModePermissionPrompt": true. This combination activates the silent auto-mode decider that emits the denial reason referenced above.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗