anthropics / anthropics/claude-code
Sandboxing unusable for JVM projects: cannot keep filesystem isolation without network isolation
- 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 requests](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20label%3Aenhancement) and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
### Problem Statement
`sandbox.enabled: true` applies filesystem **and** network isolation together. I wanted the
filesystem half only — confine reads and writes to my project — while leaving network egress
alone. There is no way to do that, and two further problems make sandboxing unworkable for a
JVM project even when egress is nominally allowed.
**Environment:** macOS 15 (Darwin 24.6.0) · Claude Code 2.1.252 · JDK 26.0.2.1 ·
JUnit Jupiter 5.10.0 · Maven
### 1. No counterpart to `sandbox.filesystem.disabled`
`sandbox.filesystem.disabled: true` turns off the filesystem half while keeping network
isolation. There is no equivalent for the network half — no `sandbox.network.disabled`, and
`allowedDomains: ["*"]` still routes traffic through the local proxy rather than bypassing it.
### 2. A JVM cannot connect to the sandbox proxy at all
This looks like a bug rather than a design choice. With the sandbox on, egress goes through a
local filtering proxy. `curl` picks it up from `HTTPS_PROXY` and works:
```console
$ curl -s -o /dev/null -w '%{http_code}\n' https://api.openai.com/v1/models
401
```
A JVM does not. `java.net.http.HttpClient` ignores the proxy environment variables, and setting
`-Dhttps.proxyHost` / `-Dhttps.proxyPort` does not help either, because the JVM cannot open a
socket to the proxy in the first place:
```java
new Socket().connect(new InetSocketAddress("localhost", 65195), 3000);
// java.net.SocketException: Operation not permitted
```
A JVM application is therefore cut off from the network entirely while sandboxed, regardless of
`allowedDomains`.
### 3. `@TempDir` fails because `java.io.tmpdir` is outside the writable set
The JVM's default `java.io.tmpdir` on macOS is `/var/folders/…/T/`, which is not among the
sandbox's writable paths, while `$TMPDIR` is set to a sandbox-managed directory
(`/tmp/claude-501`). Every JUnit test using `@TempDir` fails before it runs:
```text
ExtensionConfigurationException: Failed to create default temp directory
Caused by: java.nio.file.FileSystemException:
/var/folders/…/T/junit17117448255593413468: Operation not permitted
```
33 of my 39 unit tests failed this way until I added `-Djava.io.tmpdir="$TMPDIR"`. The
workaround is simple once known, but nothing in the failure suggests sandboxing is the cause.
### Net effect
Under sandboxing I could compile and run 39 unit tests (after the `java.io.tmpdir` workaround)
but not the integration tests that call an LLM API. I disabled sandboxing altogether and fell
back to `permissions.blockReadsOutsideWorkingDirectories`, losing the containment I wanted —
that setting restricts only the file tools (Read, Grep, Glob), not Bash.
### Proposed Solution
Any one of these would unblock the case; the first two are the smallest changes.
### 1. Let sandboxed processes reach the proxy port
Permit connections to the sandbox's own proxy from inside the sandbox. Runtimes that ignore
`HTTPS_PROXY` could then be pointed at it explicitly:
```bash
java -Dhttps.proxyHost=localhost -Dhttps.proxyPort=$PORT …
```
This needs no new setting and would make the sandbox usable for JVM, and any other runtime that
does not read proxy environment variables.
### 2. Propagate `TMPDIR` into `java.io.tmpdir`, or document the flag
Exporting `TMPDIR` at process launch already makes the JVM adopt it as `java.io.tmpdir`, so this
may just be an env-propagation gap. Failing that, a line in the sandboxing docs would save the
next person the same half-hour:
```bash
java -Djava.io.tmpdir="$TMPDIR" …
```
### 3. Add `sandbox.network.disabled`
A counterpart to the existing `sandbox.filesystem.disabled`, so the two halves can be chosen
independently:
```json
{
"sandbox": {
"enabled": true,
"network": { "disabled": true },
"filesystem": {
"allowWrite": ["/path/to/project"],
"denyRead": ["/Users/me"],
"allowRead": ["/path/to/project", "~/.m2", "~/Library/Java"]
}
}
}
```
Filesystem containment is the part most users are after; network filtering is a separate concern
and, for a local development machine behind a firewall, often not wanted at all.
### Alternative Solutions
_No response_
### Priority
High - Significant impact on productivity
### Feature Category
CLI commands and flags
### Use Case Example
Included above
### Additional Context
Included above
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 by tracing the sandbox.enabled, sandbox.filesystem.disabled, allowedDomains, and process-launch behavior described in the report. Reproduce the JVM proxy connection and @TempDir failures, then determine which behavior is covered by the existing sandbox settings. Done should leave filesystem-only isolation usable for JVM projects, with documented or supported temporary-directory handling and a clear network-isolation choice.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- java, python
- Lĩnh vực
- cli, operating-systems, security
- Loại issue
- Tính năng
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- 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
- 38/100