anthropics / anthropics/claude-code

[BUG] sandbox.credentials.files protection can be bypassed on first access to a not-yet-existing deny-listed path

Đang mở
#92,901 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:sandbox area:security bug has repro platform:linux
Ngôn ngữ chính
Python
Star
145k
Fork
23.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

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

**Environment:** Claude Code CLI 2.1.259, `sandbox.enabled: true`, `sandbox.enableWeakerNestedSandbox: true` (bubblewrap), running inside a Debian container itself running inside a macOS `container` VM.

**Config (managed-settings.json):**
```json
"sandbox": {
"credentials": {
"files": [
{ "path": "credentials.json", "mode": "deny" },
{ "path": "serviceAccountKey.json", "mode": "deny" },
{ "path": ".env", "mode": "deny" }
]
}
}
```

**Repro steps:**
1. In a directory with no `credentials.json` present, ask Claude to run via the Bash tool: `echo "hi" > credentials.json && cat credentials.json` **succeeds, discloses "hi"**. Identically reproduced with `serviceAccountKey.json` and `.env`.
2. Immediately after, ask Claude to run `cat credentials.json` (standalone) correctly **blocked**, `Permission denied`.
3. Ask Claude to run: `rm credentials.json` at this point fails with **`Device or resource busy`**, not `Permission denied` - the path is now an active mount point.
4. Deleting and recreating the file in a new invocation reproduces the bypass again on the same filename; the file is protected again on the very next invocation after that.

**Analysis:** Consistent with `sandbox.credentials.files` being enforced via a bind-mount established once per Bash-tool invocation, over whichever deny-listed paths already exist on disk at that moment (a bind-mount destination must pre-exist). A path that doesn't exist yet gets no mount for that invocation, so one compound command that creates and reads it slips through entirely.

**Impact:** Any deny-listed filename not yet present on disk can be created and read back in a single shell command, bypassing the protection on that first access - exactly the shape a prompt-injected instruction could exploit against a not-yet-created secrets file. Reproduced across three unrelated filenames, so this isn't file-specific.

### What Should Happen?

**Expected:** Protection shouldn't depend on whether the file existed before the sandboxed command started.

### Error Messages/Logs

```shell

```

### Steps to Reproduce

**Environment:** Claude Code CLI 2.1.259, `sandbox.enabled: true`, `sandbox.enableWeakerNestedSandbox: true` (bubblewrap), running inside a Debian container itself running inside a macOS `container` VM.

**Config (managed-settings.json):**
```json
"sandbox": {
"credentials": {
"files": [
{ "path": "credentials.json", "mode": "deny" },
{ "path": "serviceAccountKey.json", "mode": "deny" },
{ "path": ".env", "mode": "deny" }
]
}
}
```

**Repro steps:**
1. In a directory with no `credentials.json` present, ask Claude to run via the Bash tool: `echo "hi" > credentials.json && cat credentials.json` **succeeds, discloses "hi"**. Identically reproduced with `serviceAccountKey.json` and `.env`.
2. Immediately after, ask Claude to run `cat credentials.json` (standalone) correctly **blocked**, `Permission denied`.
3. Ask Claude to run: `rm credentials.json` at this point fails with **`Device or resource busy`**, not `Permission denied` - the path is now an active mount point.
4. Deleting and recreating the file in a new invocation reproduces the bypass again on the same filename; the file is protected again on the very next invocation after that.

**Analysis:** Consistent with `sandbox.credentials.files` being enforced via a bind-mount established once per Bash-tool invocation, over whichever deny-listed paths already exist on disk at that moment (a bind-mount destination must pre-exist). A path that doesn't exist yet gets no mount for that invocation, so one compound command that creates and reads it slips through entirely.

**Impact:** Any deny-listed filename not yet present on disk can be created and read back in a single shell command, bypassing the protection on that first access - exactly the shape a prompt-injected instruction could exploit against a not-yet-created secrets file. Reproduced across three unrelated filenames, so this isn't file-specific.

### Claude Model

Sonnet (default)

### Is this a regression?

I don't know

### Last Working Version

_No response_

### Claude Code Version

2.1.259 (Claude Code)

### Platform

Anthropic API

### Operating System

macOS

### Terminal/Shell

Terminal.app (macOS)

### Additional Information

_No response_

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Hướng nghiên cứu

Start with the sandbox.credentials.files handling used when a Bash tool invocation begins, especially how deny-listed paths are handled when absent. Reproduce the issue with `echo "hi" > credentials.json && cat credentials.json` in a sandboxed invocation, then compare it with a standalone `cat`. Done means a newly created deny-listed path is protected during that first invocation and cannot be read back.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
linux, shell
Lĩnh vực
cli, operating-systems, security
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
48/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.