Skip to content

Security Gap: Hooks Cannot Be Protected From Modification (Edit/Write tools bypass permissions.deny) #11226

Description

@aayest

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Hooks are designed to enforce behavioral restrictions, but there's no way to prevent Claude Code from modifying the hook scripts themselves using the Edit/Write tools. This creates a circular security problem where hooks cannot protect themselves.

What Should Happen?

The permissions.deny rules should prevent Edit/Write tools from modifying files in ~/.claude/hooks/ directory, protecting hooks from being tampered with.

Error Messages/Logs

- Edit/Write tools can modify hook scripts regardless of `permissions.deny` rules
- This allows Claude to bypass its own restrictions by editing the hook
- Creates a fundamental security gap in the hook system

Steps to Reproduce

  1. Create a PreToolUse hook that restricts Bash commands:
# ~/.claude/hooks/bash-compliance-enforcer.sh
#!/bin/bash
input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command // empty')

# Only allow specific commands
if [[ "$command" =~ ^git ]]; then exit 0; fi
echo "Command blocked" >&2
exit 2
  1. Register it in settings.json:
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{"type": "command", "command": "~/.claude/hooks/bash-compliance-enforcer.sh"}]
    }]
  }
}
  1. Try to protect the hook with permissions.deny:
{
  "permissions": {
    "deny": [
      "Edit(/Users/username/.claude/hooks/**)",
      "Write(/Users/username/.claude/hooks/**)"
    ]
  }
}
  1. Restart Claude Code

  2. Ask Claude to edit the hook file - it succeeds despite deny rules

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

No response

Claude Code Version

2.0.36 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Related Issues

Impact

High - Hooks are advertised as a security mechanism for enforcing policies, but if they can be modified by Claude itself, they provide only behavioral guidance, not actual enforcement.

Environment

  • Claude Code version: Latest (as of November 2025)
  • OS: macOS (Darwin 25.1.0)
  • Shell: zsh

Proposed Solutions

  1. Fix permissions.deny to work for Edit/Write tools (addresses root cause)
  2. Special-case ~/.claude/ directories in permissions system (protect Claude Code config)
  3. Add hook script integrity checking (hash validation at execution time)
  4. Immutable hook mode (load hooks at startup, prevent runtime changes)

Workarounds Attempted

Notes

This fundamentally undermines the security model of hooks as an enforcement mechanism, reducing them to trust-based behavioral guidance only. Without a way to protect hooks from self-modification, they cannot serve as reliable security boundaries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:securityarea:toolsautocloseIssue will be closed automaticallybugSomething isn't workinghas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions