anthropics / anthropics/claude-code
Sandboxing unusable for JVM projects: cannot keep filesystem isolation without network isolation
- 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 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
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- java, python
- Área
- cli, operating-systems, security
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Activo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 38/100