anthropics / anthropics/claude-code
Linux/WSL2 sandbox: socat proxy bridge starts in the background, so the first network call in a command fails
- Vorherrschende Sprache
- Python
- Sterne
- 145k
- Forks
- 23.1k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
## Summary
In the Linux/WSL2 Bash sandbox, a command whose **first** action is a network call fails with connection refused on the proxy bridge. Later calls in the same command succeed. Cause: the two `socat` bridges are started in the background and the user command runs at once, with no wait for the listeners.
Same symptom as #62743 (closed as stale). This report adds the mechanism, measurements, and a suggested fix.
## Environment
- Claude Code 2.1.269 (native binary, `latest` channel)
- WSL2, NixOS 26.05, kernel 6.18.40.1-microsoft-standard-WSL2
- bubblewrap and socat from nixpkgs
- `sandbox`: `{ "enabled": true, "autoAllowBashIfSandboxed": true, "allowUnsandboxedCommands": true, "failIfUnavailable": true }`, no `network` block
## Reproduction
Any Bash tool command that starts with a network call, for example:
```
git ls-remote https://github.com//.git HEAD
```
```
fatal: unable to access 'https://github.com//.git/': Failed to connect to github.com:443 over proxy localhost after 0 ms: Could not connect to server
```
or
```
curl -sS -o /dev/null -w '%{http_code}' https://github.com
```
```
curl: (7) Failed to connect to localhost:3128 after 0 ms: Could not connect to server
```
4 of 4 probes failed. `ss -ltn` as the first action shows no listener on 3128 yet; the same command 100 ms later shows `0.0.0.0:3128` and `0.0.0.0:1080`.
## Mechanism
The bwrap command runs the shell with this script (from the 2.1.269 binary):
```sh
socat TCP-LISTEN:3128,fork,reuseaddr UNIX-CONNECT:/tmp/claude-http-.sock >/dev/null 2>&1 &
socat TCP-LISTEN:1080,fork,reuseaddr UNIX-CONNECT:/tmp/claude-socks-.sock >/dev/null 2>&1 &
trap "kill %1 %2 2>/dev/null; exit" EXIT
-c ''
```
Nothing waits for the listen sockets to bind. Measured inside the sandbox with a `/dev/tcp` poll loop: port 3128 accepts connections 15-30 ms after the inner shell starts, while the inner shell is ready in about 3 ms. So any immediate network call loses the race.
## Suggested fix
Wait for the bridge before running the user command, for example a bounded poll in the same script:
```sh
for _ in $(seq 1 50); do (exec 3<>/dev/tcp/127.0.0.1/3128) 2>/dev/null && break; sleep 0.01; done
```
or start `socat` with a readiness signal. A user-side workaround (a guarded poll in `~/.zshenv`) makes 3/3 first calls succeed with a 20-30 ms wait, which confirms the diagnosis.
## Related: `.gitmodules` mask
`.gitmodules` in the working tree is masked with a `/dev/null` bind mount. Inside the user namespace the device node cannot be opened (`EACCES`), so:
- `git fetch` prints `warning: unable to access '.../.gitmodules': Permission denied` twice (cosmetic), and
- libgit2 users fail: `nix flake check` gives `parsing .gitmodules file: failed open - '.../.gitmodules' is locked: Permission denied (libgit2 error code = 2)`.
Masking with an empty regular file instead of a device node would avoid both.
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Rechercherichtung
Start by locating the Linux/WSL2 sandbox entry point that assembles the bwrap command and launches the two socat bridges, then reproduce with the first-action curl or git ls-remote examples. Verify that both listeners are usable before the user shell runs, and check the .gitmodules mask behavior separately; done means first network calls succeed without the race and libgit2 can read the masked path.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- bash, git, linux
- Bereich
- cli, infrastructure, networking, operating-systems, security
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Aktiv
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 52/100