anthropics / anthropics/claude-code

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

Abierto
#87,935 1 comentario 0 reacciones 0 asignados Ver en GitHub
area:bash area:sandbox bug has repro platform:linux reproduced stale
Lenguaje dominante
Python
Estrellas
145k
Forks
23.1k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

### 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.

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
bash, linux, python
Área
cli, operating-systems, security
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Activo
Claridad
Bastante claro
Aptitud para principiantes
55/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.