[BUG] Regression in 2.1.259: rg reading stdin in a pipeline is treated as a search of '.' and prompts (auto mode bypassed) when a Read() deny rule covers a file under the cwd

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

Preflight Checklist

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

What's Wrong?

Since 2.1.259, when a Read() deny rule covers a file somewhere under the current working directory, every rg invocation that has no path operand prompts for manual approval. In a pipeline, rg with no path reads stdin and never touches the filesystem, but the Bash read-scope check models it as rg on '.' and escalates:

rg on '.' would read '<absolute path of the cwd>', which the deny rule Read(**/private-notes.md) covers; only you can approve running it anyway.

The escalation carries classifier_approvable: false, so in auto mode the classifier is skipped and a human has to click through every cmd | rg pattern. grep in the same position is handled correctly. An explicit stdin operand (rg pattern -) does not help.

In this setup every repository keeps a private-notes.md at its root that the deny rule protects, so nearly every filter pipeline the model writes now prompts, and the auto-mode classifier can do nothing about it.

Results on 2.1.259, same checkout, same deny rule, captured headless with --input-format stream-json --output-format stream-json --permission-prompt-tool stdio:

| Command | Result |
| --- | --- |
| rg -c pattern /tmp/dir/a.txt \| rg -v ':0$' \| wc -l | prompts (reason above) |
| printf 'a\nb\n' \| rg a - | prompts (same reason) |
| printf 'a\nb\n' \| grep a | runs |
| rg -c pattern /tmp/dir/*.txt (literal path with a glob) | runs |
| echo "$(rg -c pattern /tmp/dir/a.txt \| wc -l)" (substitution, literal file) | runs |
| rg -n pattern src/sub/dir/ (directory with no covered file below it) | runs |
| git diff --stat; git grep -n pattern -- src/sub | runs |

The first row was also run against the 2.1.258 binary with the same settings and checkout: it runs without a prompt.

What Should Happen?

An rg invocation with no path operand, or with -, inside a pipeline reads stdin and should not be modelled as a search of .. It should be treated the way grep already is in the same position: no deny-rule escalation, so the permission mode decides as it did before 2.1.259.

Error Messages/Logs

rg on '.' would read '<absolute path of the cwd>', which the deny rule Read(**/private-notes.md) covers; only you can approve running it anyway.

# can_use_tool control request for the same command:
"tool_name": "Bash",
"decision_reason_type": "subcommandResults",
"classifier_approvable": false,
"matched_ask_rule": null

Steps to Reproduce

  1. Put a Read() deny rule in ~/.claude/settings.json:

``json
{ "permissions": { "deny": ["Read(**/private-notes.md)"] } }
``

  1. Create a directory whose root contains a file the rule covers, plus an ordinary file:

``sh
mkdir -p /tmp/rgpipe && printf 'private\n' > /tmp/rgpipe/private-notes.md && printf 'ok\n' > /tmp/rgpipe/a.txt
``

  1. Start Claude Code 2.1.259 in /tmp/rgpipe in auto mode and have it run:

``sh
rg -c ok /tmp/rgpipe/a.txt | rg -v ':0$' | wc -l
``

The prompt above appears, with classifier_approvable: false, so auto mode cannot approve it.

  1. Have it run printf 'a\nb\n' | grep a. No prompt.
  2. Repeat step 3 on 2.1.258. No prompt.

The commands in the table were run in a repository checkout whose root holds the covered file; the steps above are that setup reduced to a temp directory.

Claude Model

Other: Fable 5.1 (claude-fable-5-1). The check is static and does not depend on the model.

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.258

Claude Code Version

2.1.259 (Claude Code), the native binary bundled with the VS Code extension 2.1.259; the headless reproduction used the same binary.

Platform

Anthropic API (claude.ai subscription sign-in)

Operating System

Ubuntu/Debian Linux: Ubuntu 26.04.1 LTS, kernel 7.0.0-30-generic, ripgrep 15.1.0

Terminal/Shell

Other: VS Code extension chat panel; the Bash tool runs zsh. Also reproduced headless with claude -p --input-format stream-json --output-format stream-json --permission-prompt-tool stdio.

Additional Information

Two reports filed today trace back to the same 2.1.259 changelog line and form a cluster with this one:

Fixed Bash Read() deny rules not covering files given as option values (--ignore-revs-file=.env, -f.env, @file), git diff/git grep file operands, or cd DIR && cat FILE compounds; grep -r/cp -r over a directory holding a denied file now asks
  • #91681: rg <pattern> . with a hidden-file rule (Read(**/.env)) prompts although no covered file exists and ripgrep skips dotfiles by default.
  • #91683: cd DIR && grep … prompts in bypassPermissions mode when any Read() rule is configured.

This report differs from both: rg has no path operand at all and reads stdin, the covered file exists and is not hidden, and grep in the identical position is unaffected. Fixing the hidden-file modelling from #91681 would not fix this case.

Workaround for now: have the model use grep for pipe filtering, or remove the deny rule. The rule protects a real file in every repository, so removing it is not an acceptable long-term answer.

_Drafted by Claude (Anthropic AI assistant)._

View original on GitHub ↗