anthropics / anthropics/claude-code

Sandboxed Bash wedges permanently when the working directory is on a read-only filesystem (no cwd recovery)

Aperta
#87,935 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
area:bash area:sandbox bug has repro platform:linux reproduced stale
Lingua principale
Python
Stelle
145k
Fork
23.1k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) 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?

When the sandboxed Bash tool's working directory ends up on a read-only filesystem (e.g. a read-only bind mount the agent `cd`s into), **every subsequent Bash command fails during sandbox setup, before the command runs**, and the session cannot recover on its own.

Because setup fails before the command executes, even a `cd` back to a writable directory never runs — the shell is sealed out of its own recovery. Read/Edit/Glob/Grep still work (they don't spawn a sandboxed shell), so only the Bash tool dies. A single `cd` into a read-only mount kills Bash for the rest of the session.

**Root cause.** For every Bash command, sandbox setup prepares two things **under the shell's current working directory**, before bwrap launches:
1. a `.claude/settings.json` write-mask (a bind rule) — bwrap must *create* the mount-point file for it, which fails on a read-only fs;
2. an atomic-write staging dir `/.claude/.cc-writes`, created with a plain `mkdir`, which also fails on a read-only fs.

Both run on **every** invocation (a bare `pwd` triggers them), keyed on the cwd persisted from the *previous* command — so once the cwd is a read-only mount, the next command's setup targets `/.claude/…` and aborts. The intent ("prepare to write next to the working directory") is meaningless on a filesystem nothing can write to, but setup treats the failure as fatal.

### What Should Happen?

A read-only working directory should make the per-command scratch/mask setup a no-op (nothing can be written there anyway) and Bash commands should keep working — or the session should recover the cwd to a writable path, exactly as it already does when the working directory has been *deleted* (it logs `Shell CWD "…" no longer exists, recovering to "…"` and resets the tracked cwd).

### Error Messages/Logs

```shell
bwrap: Can't create file at /.claude/settings.json: Read-only file system
bwrap: Can't mkdir /.claude: Read-only file system
```

### Steps to Reproduce

Minimal, no specific project or model. Any Linux host with the CLI:

1. Create a read-only directory the agent can `cd` into:
```
mkdir -p /tmp/ro && echo hello > /tmp/ro/file.txt
sudo mount --bind /tmp/ro /tmp/ro
sudo mount -o remount,ro,bind /tmp/ro
# (or in a container, mount a volume read-only: -v /tmp/ro:/work/ro:ro)
```
2. In a session with the Bash sandbox enabled, run each as a separate Bash tool call:
```
cd /tmp/ro && pwd # OK -> /tmp/ro
ls # OK (first command after the cd)
pwd # FAILS -> bwrap: Can't mkdir /tmp/ro/.claude: Read-only file system
cd /tmp && pwd # FAILS identically -- the escape never runs
```
From the 3rd command on, every command (including `echo`, `true`, or the `cd` that would fix it) fails at sandbox setup.

**Isolating the mechanism (no CLI needed)** — the two failing setup operations, reproduced directly with bubblewrap:
```
bwrap --dev-bind / / --ro-bind /tmp/ro /tmp/ro -- sh -c 'cd /tmp/ro && pwd'
# -> /tmp/ro (exit 0; denying the mount as a whole is fine)
bwrap --dev-bind / / --ro-bind /dev/null /tmp/ro/.claude/settings.json -- true
# -> bwrap: Can't create file at /tmp/ro/.claude/settings.json: Read-only file system (exit 1)
```

### Claude Model

_No response_

### Is this a regression?

No, this never worked

### Last Working Version

_No response_

### Claude Code Version

Reproduced on 2.1.226 and 2.1.229; present on 2.1.235. bubblewrap 0.11.0. Independent of model and API platform.

### Platform

Other

### Operating System

Other Linux

### Terminal/Shell

Non-interactive/CI environment

### Additional Information

**The asymmetry that points at a small fix:** the tool already recovers when the working directory has been *deleted* (ENOENT → resets the tracked cwd to a writable fallback, `Shell CWD "…" no longer exists, recovering to "…"`), but not when the cwd is *read-only* (EROFS on the staging setup). Either fix is sufficient:

1. **Tolerate `EROFS`/`EACCES`** when pre-creating the per-command staging dir (`.claude/.cc-writes`) and the settings write-mask under the cwd — a read-only fs cannot host a planted settings file or a staging dir, so skipping them there is safe.
2. **Extend the existing deleted-cwd recovery** to also reset the cwd when it is read-only.

**Related** (same "sandbox setup must write under a read-only path" class, other angles): #50781 (`Can't create file at .zshrc` kills all Bash), #46560 (cwd is `~/.claude`), #25603 (denyWithinAllow artifacts in the working dir), #43096 (`/tmp/claude` TMPDIR chicken-and-egg). This report is the **general case**: any read-only mount reached by a normal `cd`, with the deleted-cwd-recovers / read-only-cwd-wedges asymmetry.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

Reproduce the failure on Linux with the Bash sandbox and bubblewrap commands from the report, using a read-only mounted working directory. Trace the per-command sandbox setup for the settings write-mask and .claude/.cc-writes staging directory, then compare it with the existing deleted-cwd recovery; done means Bash commands continue working or the cwd recovers after entering a read-only mount.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
bash, linux, python
Ambito
cli, operating-systems, security
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
55/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.