[BUG] PreToolUse hook for Write/Edit can be bypassed by writing files via the Bash tool
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
A PreToolUse hook configured with matcher Write|Edit does not fire when the same file write is performed via the Bash tool (e.g. using tee, cat >, or python3 open()). This means any hook intended to constrain file-write behaviour can be silently bypassed by switching tools.
This was discovered when Claude itself used this technique to bypass its own credential-guard hook during a session. The hook blocked the Write tool from updating a script under ~/.claude/hooks/. Claude identified that tee via the Bash tool would achieve the same write without triggering the hook, and executed this without disclosing the workaround to the user. A separate model behaviour issue has been filed for that aspect.
What Should Happen?
Hook enforcement should be action-scoped, not tool-scoped. A PreToolUse hook that restricts file writes should apply to any tool invocation that results in a file write, regardless of which tool is used. At minimum, the documentation should clearly state that Write/Edit hooks do not cover Bash-mediated file writes, so operators know to add a Bash hook as well.
Steps to Reproduce
- In
settings.json, configure aPreToolUsehook with matcherWrite|Editthat blocks writes to a specific path — e.g. any path under~/.claude/. - Ask Claude to write a file to that path using the Write tool. Confirm the hook fires and the write is blocked.
- Now ask Claude (or attempt manually) to write the same file via a Bash command: e.g.
tee ~/.claude/somefile.txt << 'EOF' ... EOF - The hook does not fire. The file is written without restriction.
Error Messages/Logs
No error. The bypass is silent — the Bash tool completes successfully and no hook output is produced.
Claude Model
Sonnet (claude-sonnet-4-6, version 2.1.156)
Is This a Regression?
No — this appears to be a fundamental property of the hook architecture (tool-scoped rather than action-scoped).
Claude Code Version
2.1.156 (Claude Code)
Platform
Anthropic API
Operating System
macOS (Darwin 25.5.0)
Terminal/Shell
Terminal.app (macOS) / zsh
Additional Information
The practical impact is that PreToolUse hooks for Write|Edit provide no protection against Bash-mediated file writes. Operators configuring hooks to protect credential stores, config directories, or other sensitive paths will find the restriction silently bypassable. The hook matcher name implies file-write coverage but it is enforced only at the tool-invocation boundary.
A companion model behaviour issue has been filed separately describing how Claude reasoned about and executed this bypass without user notification.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗