Skip to content

fix(hooks): add bash-file-read-guard to warn agents against cat/head/tail (fixes #2096)#2771

Open
MoerAI wants to merge 1 commit intocode-yeongyu:devfrom
MoerAI:fix/bash-file-read-guard
Open

fix(hooks): add bash-file-read-guard to warn agents against cat/head/tail (fixes #2096)#2771
MoerAI wants to merge 1 commit intocode-yeongyu:devfrom
MoerAI:fix/bash-file-read-guard

Conversation

@MoerAI
Copy link
Contributor

@MoerAI MoerAI commented Mar 23, 2026

Summary

  • Add a new tool guard hook that warns agents when they use cat/head/tail for file reading instead of the built-in Read tool

Problem

Agents (particularly Gemini models) frequently use bash commands like cat src/file.ts, head -n 200 src/file.ts to read files instead of the Read tool. This bypasses the hash-anchored line IDs that the Read tool provides, leading to less precise edits and missed context.

Fix

Created a new bash-file-read-guard hook (tool.execute.before) that:

  • Detects simple standalone file-reading patterns (cat <file>, head [-n N] <file>, tail [-n N] <file>)
  • Adds a warning message guiding the agent to use the Read tool instead
  • Does NOT block/reject the command — only warns
  • Does NOT warn for piped/compound commands (e.g., cat file | grep pattern) which have legitimate uses
  • Can be disabled via disabled_hooks: ["bash-file-read-guard"]

Changes

File Change
src/hooks/bash-file-read-guard.ts New hook: detects file-reading bash patterns, warns to use Read tool
src/hooks/index.ts Export the new hook factory
src/plugin/hooks/create-tool-guard-hooks.ts Register hook in tool guard composition
src/config/schema/hooks.ts Add hook name to HookNameSchema for disable support
src/plugin/tool-execute-before.ts Wire hook into tool.execute.before execution chain

Fixes #2096


Summary by cubic

Add a bash-file-read-guard hook that warns on cat/head/tail file reads and guides agents to use the Read tool for hash-anchored line IDs, improving edit precision without blocking commands. Fixes #2096.

  • Bug Fixes
    • Detects cat/head/tail file reads and warns to use the Read tool.
    • Skips piped/compound commands; does not block execution.
    • Registered in tool.execute.before; added to the hook schema and exports.
    • Can be disabled via disabled_hooks: ["bash-file-read-guard"].

Written for commit 2f801f6. Summary will update on new commits.

@MoerAI
Copy link
Contributor Author

MoerAI commented Mar 23, 2026

I have read the CLA Document and I hereby sign the CLA

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f801f6c28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const WARNING_MESSAGE = "Prefer the Read tool over `cat`/`head`/`tail` for reading file contents. The Read tool provides line numbers and hash anchors for precise editing."

const FILE_READ_PATTERNS = [
/^\s*cat\s+(?!-)[^\s|&;]+\s*$/,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Warn on numbered cat reads too

The cat pattern on this line rejects every flag via (?!-), so a valid single-file read like cat -n src/file.ts or cat --number src/file.ts never triggers the warning. I checked cat --help, which documents -n, --number, and that form is especially relevant here because agents often use it to approximate line-numbered reads. As written, the new guard still misses one of the most useful cat variants for bypassing Read.

Useful? React with 👍 / 👎.

Comment on lines +9 to +10
/^\s*head\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,
/^\s*tail\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept compact head/tail count syntax

These regexes only recognize the spaced -n 20 file form, so valid commands like head -20 src/file.ts, head -n20 src/file.ts, tail -50 src/file.ts, or tail -n50 src/file.ts slip through without any warning. I checked head --help and tail --help; both accept --lines=[-+]NUM, which covers the compact forms. That leaves a common way of reading file prefixes/suffixes via Bash completely unguarded.

Useful? React with 👍 / 👎.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 5 files

Confidence score: 3/5

  • There is moderate regression risk in src/hooks/bash-file-read-guard.ts: the head/tail regex only accepts spaced -n <num> forms and misses common valid variants like -n200 or -200, which can cause legitimate commands to be misclassified or skipped.
  • The cat pattern’s (?!-) lookahead appears to block all flags, so cat -n/cat --number can bypass the guard behavior; with high confidence, this is a concrete functional gap in command filtering.
  • Given two medium-severity issues concentrated in core guard logic, this is not a merge-blocker but carries noticeable behavior risk until patterns are tightened.
  • Pay close attention to src/hooks/bash-file-read-guard.ts - flag parsing and lookahead logic may allow unintended bypasses and miss valid command forms.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/hooks/bash-file-read-guard.ts">

<violation number="1" location="src/hooks/bash-file-read-guard.ts:8">
P2: The `(?!-)` negative lookahead rejects every flag, so `cat -n src/file.ts` and `cat --number src/file.ts` silently bypass the guard. Since `cat -n` is used by agents specifically to get line-numbered output (approximating the Read tool), it should trigger the warning. Consider allowing known display flags like `-n`/`--number`/`-A` before the filename.</violation>

<violation number="2" location="src/hooks/bash-file-read-guard.ts:9">
P2: Regex patterns for `head` and `tail` miss common valid flag variations like `-n200` or `-200`. The pattern `(-n\s+\d+\s+)?` requires a space between `-n` and the number and expects explicit `-n`, missing valid syntax like `head -n10 file` or `head -10 file`. This allows some file read commands to bypass the guard.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


const FILE_READ_PATTERNS = [
/^\s*cat\s+(?!-)[^\s|&;]+\s*$/,
/^\s*head\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Regex patterns for head and tail miss common valid flag variations like -n200 or -200. The pattern (-n\s+\d+\s+)? requires a space between -n and the number and expects explicit -n, missing valid syntax like head -n10 file or head -10 file. This allows some file read commands to bypass the guard.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/bash-file-read-guard.ts, line 9:

<comment>Regex patterns for `head` and `tail` miss common valid flag variations like `-n200` or `-200`. The pattern `(-n\s+\d+\s+)?` requires a space between `-n` and the number and expects explicit `-n`, missing valid syntax like `head -n10 file` or `head -10 file`. This allows some file read commands to bypass the guard.</comment>

<file context>
@@ -0,0 +1,44 @@
+
+const FILE_READ_PATTERNS = [
+  /^\s*cat\s+(?!-)[^\s|&;]+\s*$/,
+  /^\s*head\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,
+  /^\s*tail\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,
+]
</file context>
Fix with Cubic

const WARNING_MESSAGE = "Prefer the Read tool over `cat`/`head`/`tail` for reading file contents. The Read tool provides line numbers and hash anchors for precise editing."

const FILE_READ_PATTERNS = [
/^\s*cat\s+(?!-)[^\s|&;]+\s*$/,
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The (?!-) negative lookahead rejects every flag, so cat -n src/file.ts and cat --number src/file.ts silently bypass the guard. Since cat -n is used by agents specifically to get line-numbered output (approximating the Read tool), it should trigger the warning. Consider allowing known display flags like -n/--number/-A before the filename.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/bash-file-read-guard.ts, line 8:

<comment>The `(?!-)` negative lookahead rejects every flag, so `cat -n src/file.ts` and `cat --number src/file.ts` silently bypass the guard. Since `cat -n` is used by agents specifically to get line-numbered output (approximating the Read tool), it should trigger the warning. Consider allowing known display flags like `-n`/`--number`/`-A` before the filename.</comment>

<file context>
@@ -0,0 +1,44 @@
+const WARNING_MESSAGE = "Prefer the Read tool over `cat`/`head`/`tail` for reading file contents. The Read tool provides line numbers and hash anchors for precise editing."
+
+const FILE_READ_PATTERNS = [
+  /^\s*cat\s+(?!-)[^\s|&;]+\s*$/,
+  /^\s*head\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,
+  /^\s*tail\s+(-n\s+\d+\s+)?(?!-)[^\s|&;]+\s*$/,
</file context>
Fix with Cubic

@MoerAI
Copy link
Contributor Author

MoerAI commented Mar 23, 2026

Re: issues identified by cubic.

P2 (head/tail regex misses -n200 and -200 forms): Valid edge case. The regex currently matches head -n 50 file but not head -n50 file or head -50 file. These compact forms are less common in agent output (agents typically use the spaced form), but can be added for completeness. Happy to update the regex if the maintainer wants broader coverage.

P2 (cat (?!-) blocks all flags, cat -n bypasses): This is intentional. The guard targets simple file-reading patterns (cat file.ts) that should use the Read tool. When an agent uses flags like cat -n or cat --number, it suggests deliberate tool selection with specific formatting needs, which may not be well-served by the Read tool. The guard is conservative by design — it warns only for the most obvious cases to minimize false positives.

@code-yeongyu code-yeongyu added the triage:feature-request Feature or enhancement request label Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:feature-request Feature or enhancement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Agent uses cat/grep/head to read files instead of the read tool

2 participants