anthropics / anthropics/claude-code

[BUG] Bash cd-compound-read guard prompts on absolute cd targets whenever a Read() deny rule exists (Windows Git Bash, 2.1.257-2.1.259)

Open
#91,650 10 comments 58 reactions 0 assignees View on GitHub
area:bash area:permissions bug has repro platform:windows
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## Environment

- Claude Code 2.1.259 native install (2.1.257 and 2.1.258 binaries on the same machine reproduce it), Windows 11 Pro 10.0.26200, Git Bash as the Bash tool shell
- `permissions.defaultMode: auto`; user settings carried six `Read()` deny rules: `Read(.env)`, `Read(**/.env)`, `Read(**/.env.*)`, `Read(**/credentials*)`, `Read(**/*.pem)`, `Read(**/*.key)`, plus Bash and Edit denies

## What happens

Any compound Bash command that contains `cd` and a `;`, or `cd && grep -r `, stops for approval on every relative-path read, even when the cd target is an absolute literal path:

> sed reads a file by a relative path after a cd in a compound command; which file that is cannot be resolved statically while a Read() deny rule is configured, so this needs approval.

Decision reason: `Compound command contains cd with a relative file read while a Read() deny rule exists`, `bashMissKind: "cd-compound-read"`.

The prompt appears in auto mode and, as observed by the operator, in bypass-permissions mode. Subagent Bash calls surface it as a manual approval in the parent session, so with several subagents running it was one prompt per file read.

## Measured matrix

Headless probes with `claude -p --permission-mode auto --model haiku --tools Bash`, exact tool input captured from `--output-format stream-json`, working directory equal to the cd target. Same settings for every row.

| Command (2.1.259) | Result |
|---|---|
| `cd D:/dev/ && sed -n 1,2p README.md` | allowed |
| `cd D:/dev/ && sed -n 1,2p README.md; echo ===` | prompt, cd-compound-read |
| `cd D:/dev/; sed -n 1,2p README.md` | prompt, cd-compound-read |
| `cd D:/dev/ && grep -rn pat sub/dir/ \| head -2` | prompt: "grep on 'sub/dir/' after a cd would search a directory that cannot be determined here, and a Read() deny rule is configured" |
| `sed -n 1,2p README.md` | allowed |

2.1.258: the `&& sed …; echo …; grep -r …` and `&& grep -r sub/dir/ \| head` shapes prompt with the cd-compound-read wording; the pure `&& sed` chain is allowed. The guard's code is identical across the 2.1.257, 2.1.258 and 2.1.259 binaries apart from minified identifiers; I have no older binary to date its introduction. Prompts began for us between 2.1.257 (installed Sep 1) and 2.1.259 (Sep 2).

## Observations

- The cd target is an absolute literal in every prompting case, so "cannot be resolved statically" does not hold. The resolver appears to give up whenever the compound contains `;`, including for a read that sits before the `;` in the `&&` chain and therefore runs under the known directory.
- The grep wording on 2.1.259 names the wrong operand. `cd /d/dev/ && echo "=== X ==="; grep -rn "X" --include=*.cs .` produced "grep on '--include=*.cs' after a cd would search a directory that cannot be determined here". The search path is `.`.
- Removing the six `Read()` deny rules from user settings stopped the prompts in the interactive sessions at once (settings reload live). In headless `-p --permission-mode auto` the same command still prompts with every `Read()` and `Edit()` rule removed from user and project settings, so something else arms the check there; I could not identify what.
- Headless `-p --dangerously-skip-permissions` allowed every shape on 2.1.258 and 2.1.259.

## Expected

A `cd` to an absolute literal path followed by relative reads is resolvable, and the guard already resolves it for the pure `&&` chain. A `;` later in the compound should not un-resolve a read that runs under the `&&`. The grep wording should name the actual path operand.

## Related

#86619 covered the write-side variant of the same cd-compound analysis on Windows Git Bash (fixed in 2.1.233). This is the read side, keyed on the presence of `Read()` deny rules.

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the supplied command matrix in Windows Git Bash, focusing on the cd-compound-read guard and its behavior with Read() deny rules. Compare the read-side analysis with related issue #86619; done means absolute cd targets remain resolvable despite later semicolons, and grep prompts identify the actual search path.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash
Domain
cli, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.