If your file-guard hook is registered on Read, it never sees cat
I wrote a PreToolUse hook to keep one file out of the model's context. Registered it on Read , exit 2. Asked Claude Code to read the file with the Read tool. It stopped. Good. Then I asked it to read the same file with cat . The hook was never called. Not "called and passed" — never called. The contents went straight into the transcript. What did stop the cat was a one-line deny rule in…
The report examines the reach of a custom "file-guard" hook when registered on the Read action in Claude Code 2.1.246 for Linux. When the hook is registered on Read and invoked with the cat command, it successfully blocks access to the file, preventing its contents from being passed to the model. However, when cat is replaced with the Read tool, the hook fails to fire, allowing the file's contents to be ingested by the model.
To test this behavior, the reporter set up a series of conditions in isolated directories, each with its own settings.json file and hook configuration. Two hooks were used: one that simply echoes stdin and exits, and another that blocks stdin and exits with a non-zero status. One rule was set before all tests: a zero-byte hook log does not necessarily indicate the hook did not fire, as the log can be empty due to the run occurring.
The reporter ran tests with Read via cat, Read via the Read tool, Bash, and two additional conditions (D and F) to measure the hook's behavior. Conditions U and F, both using a blocker hook on Read, showed identical results. Condition U, which ran on the Read tool, did not have a surviving August output, so its findings from the 2.1.258 run are included.
One surprising finding was that a deny rule applied to a specific file (./secret.txt) blocked access when read via cat, but not when read via the Read tool. The hook message indicated a directory-level denial, whereas the rule specified a file-level denial. To clarify this discrepancy, the reporter ran a separate test comparing a deny rule applied to a specific file with the same rule applied to a harmless file. The results showed that the deny rule still applied per-file, with only the message wording being misleading.
Another surprising outcome involved condition H, where the deny rule blocked access to the file when read via the Read tool, even though the model was able to invoke head and sed commands to access the file's contents. The documentation specifies that deny rules apply to file commands recognized by Claude Code in Bash, such as cat, head, tail, and sed, but does not explicitly limit the rules to within the specified commands.
The reporter concludes that the file-guard hook registered on Read in Claude Code 2.1.246 indeed blocks file access when read via cat, but not when read via the Read tool. This distinction is important for developers seeking to control file access within their Claude Code instances, as the behavior may vary depending on the specific method used to read files.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.