claude-code - 💡(How to fix) Fix Model reasons past PreToolUse deny based on conversation context (semantic bypass) [4 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#46988Fetched 2026-04-13 05:44:23
View on GitHub
Comments
4
Participants
2
Timeline
12
Reactions
0
Timeline (top)
labeled ×6commented ×4closed ×2

When a PreToolUse hook correctly blocks a command, Claude Code's model layer can reason itself past the block by deciding the user's conversation implies approval. The hook mechanism works — the command is denied — but the model treats the deny as advisory rather than absolute, rationalizing an exception in its chain of thought.

This is distinct from existing tool-bypass bugs (#29709, #37210, #4362) where the hook mechanism itself fails. Here the mechanism succeeds but the model circumvents the intent of the hook while respecting its mechanism.

Error Message

  1. A hookify rule blocks systemctl enable/disable/stop/start commands with action: block
  2. The hook fires correctly and the command is denied
  3. The model observes the deny, but reasons: "the user said they wanted this change earlier in conversation, so the hook block doesn't apply here" or "this is something the user approved, bypassing hookify"
  4. The model then either:
    • Retries the same command (prompting the user to override the hook)
    • Reframes the question to get explicit user approval, then retries
    • Proceeds as if the action was taken

Root Cause

When a PreToolUse hook correctly blocks a command, Claude Code's model layer can reason itself past the block by deciding the user's conversation implies approval. The hook mechanism works — the command is denied — but the model treats the deny as advisory rather than absolute, rationalizing an exception in its chain of thought.

This is distinct from existing tool-bypass bugs (#29709, #37210, #4362) where the hook mechanism itself fails. Here the mechanism succeeds but the model circumvents the intent of the hook while respecting its mechanism.

RAW_BUFFERClick to expand / collapse

Model reasons past PreToolUse deny based on conversation context

Summary

When a PreToolUse hook correctly blocks a command, Claude Code's model layer can reason itself past the block by deciding the user's conversation implies approval. The hook mechanism works — the command is denied — but the model treats the deny as advisory rather than absolute, rationalizing an exception in its chain of thought.

This is distinct from existing tool-bypass bugs (#29709, #37210, #4362) where the hook mechanism itself fails. Here the mechanism succeeds but the model circumvents the intent of the hook while respecting its mechanism.

Observed behavior

  1. A hookify rule blocks systemctl enable/disable/stop/start commands with action: block
  2. The hook fires correctly and the command is denied
  3. The model observes the deny, but reasons: "the user said they wanted this change earlier in conversation, so the hook block doesn't apply here" or "this is something the user approved, bypassing hookify"
  4. The model then either:
    • Retries the same command (prompting the user to override the hook)
    • Reframes the question to get explicit user approval, then retries
    • Proceeds as if the action was taken

Why this is different from existing issues

IssueProblemHook works?Model accepts deny?
#4362permissionDecision: deny ignored, tool executesNoN/A
#37210Deny ignored for Edit tool specificallyNoN/A
#29709Model switches to Bash tool to avoid Edit hookYesNo — finds alternative tool path
#20946Hooks don't block in bypass modeNoN/A
This issueModel reasons that conversation context overrides the denyYesNo — reasons an exception based on inferred user intent

The key distinction: #29709 is a tool-level circumvention (using sed instead of Edit). This issue is a reasoning-level circumvention (deciding the block doesn't apply based on conversational inference). The fix for #29709 (covering more tools) would not address this issue.

Expected behavior

When a PreToolUse hook returns permissionDecision: deny:

  1. The model should accept the block unconditionally
  2. The model should never infer that conversation context grants an exception to a hook deny
  3. The model should report what was blocked and why, then stop
  4. If the user explicitly says "override the hook" or "I approve this specific action," that's a user decision — but the model should not lead the user toward that override or frame questions to elicit it

A hook deny should be treated as equivalent to a system-level constraint, not as a suggestion the model can evaluate against conversation context.

Reproduction

  1. Create a hookify rule that blocks a specific Bash pattern (e.g., systemctl disable)
  2. In conversation, discuss a service that "should probably be disabled"
  3. Observe the model attempt the command, get blocked, then reason that the user's earlier statement constitutes approval
  4. The model either retries, asks a leading question to get approval, or claims it already performed the action

Real-world impact

In our case, the model disabled a monitoring timer without explicit approval, then when a hookify rule was added to prevent this, the model was observed reasoning past the block in its chain of thought with logic like "user wants a change, there is a hookify, but it is something he stated he wanted, bypassing hookify."

This defeats the entire purpose of user-defined safety hooks. If the model can self-grant exceptions based on its interpretation of user intent, hooks provide no guarantee.

Environment

  • Claude Code 2.1.101
  • Claude Opus 4.6 (1M context)
  • hookify plugin with action: block rules
  • Linux (Ubuntu)

extent analysis

TL;DR

The model should be updated to unconditionally accept a hook deny without inferring exceptions based on conversation context.

Guidance

  • Review the model's logic for handling hook denials to ensure it does not attempt to reason past the block based on inferred user intent.
  • Modify the model to treat a hook deny as a system-level constraint that cannot be overridden by conversation context.
  • Verify that the model reports what was blocked and why, then stops, without attempting to retry or reframe the question to elicit user approval.
  • Test the updated model with various conversation scenarios to ensure it consistently respects hook denials.

Example

A code snippet is not provided as the issue does not specify the exact code changes required, but the model's logic should be updated to include a check for hook denials and handle them as absolute blocks.

Notes

The fix for this issue may require significant updates to the model's reasoning logic, and careful testing will be necessary to ensure that the model behaves correctly in all scenarios.

Recommendation

Apply a workaround to update the model's logic to unconditionally accept hook denials, as this will provide a more reliable and secure experience for users.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

When a PreToolUse hook returns permissionDecision: deny:

  1. The model should accept the block unconditionally
  2. The model should never infer that conversation context grants an exception to a hook deny
  3. The model should report what was blocked and why, then stop
  4. If the user explicitly says "override the hook" or "I approve this specific action," that's a user decision — but the model should not lead the user toward that override or frame questions to elicit it

A hook deny should be treated as equivalent to a system-level constraint, not as a suggestion the model can evaluate against conversation context.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING