[BUG] grep -r over any directory prompts on a Read(**/…) deny rule even when the tree contains no matching file (2.1.259)

Status Open
Reported on v2.1.259
Maintainer reply None cached
Activity 1 comment · opened Sep 3, 2026

Preflight Checklist

  • [x] I have searched existing issues; closest are #91681, #91778, #91751 —

this is the plain-grep, non-hidden-file, file-absent case

  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code (2.1.259)

What's Wrong?

Since 2.1.259, a Read() deny rule whose pattern starts with ** makes every
recursive grep -r <dir> prompt for approval, even when the searched directory
contains no file matching the pattern at any depth.

Minimal config (~/.claude/settings.json):

{ "permissions": { "deny": ["Read(**/denied.txt)"] } }

In a clean directory that has no denied.txt anywhere:

mkdir -p /tmp/cleanrepo && printf 'hello\n' > /tmp/cleanrepo/a.txt

Running grep -rn hello /tmp/cleanrepo produces:

grep on '/tmp/cleanrepo' would read '/tmp/cleanrepo', which the deny rule
Read(**/denied.txt) covers; only you can approve running it anyway.

Do you want to proceed?
> 1. Yes
  2. No

Note: this is not a permission-mode or precedence question. A Read() deny
rule correctly outranks bypassPermissions and the other permission modes.
The report is about a false positive: a **-anchored deny rule is treated as
covering every directory, so the search is escalated even when nothing in the
tree matches the rule.

What Should Happen?

A recursive search should only be escalated when the searched directory
actually contains a file matching the deny pattern. A leading ** gives the
pattern no literal directory anchor, but that should not make the rule match
every directory; the current behaviour appears to treat **/denied.txt as
"could be under any directory", so every directory-rooted grep -r escalates.

Steps to Reproduce

  1. mkdir -p /tmp/cleanrepo && printf 'hello\n' > /tmp/cleanrepo/a.txt

(no denied.txt at any depth).

  1. Put { "permissions": { "deny": ["Read(**/denied.txt)"] } } in

~/.claude/settings.json.

  1. Start Claude Code 2.1.259 in /tmp/cleanrepo and have it run

grep -rn hello /tmp/cleanrepo.

  1. The prompt above appears. Approving and re-running prompts again, on every

directory.

Is this a regression?

Yes, as far as I can tell. I auto-update daily and don't record the exact
version per day, but the same commands did not prompt yesterday or the day
before; the 2.1.259 changelog also attributes this escalation to 2.1.259
("now asks").

Related

Changelog 2.1.259: "grep -r/cp -r over a directory holding a denied file
now asks".

Related false-positive reports in this cluster:

  • #91681 — Read(**/.env) prompts on every rg search (hidden files, rg)
  • #91778 — grep -r --include ignores filters (denied file present)
  • #91751 — rg reading stdin modeled as a search of .

This report differs: plain grep (no --include), a non-hidden denied
filename, and a directory that contains no matching file at all.

Environment

  • Claude Code 2.1.259 (native Linux binary)
  • OS: Debian GNU/Linux
  • Shell: zsh
  • Permission mode: bypassPermissions (the mode this was observed in). A

Read() deny rule correctly still applies under bypassPermissions; the
bug is the false-positive escalation, not the mode.

  • Model: the check is static and model-independent

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗