Sandbox egress proxy re-originates TLS even with access: full, causing Cloudflare-fronted upstreams to reset the connection
- Dominant language
- TypeScript
- Stars
- 22.5k
- Forks
- 3.1k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 715
Description
### Investigation Summary
OpenCode Zen (Cloudflare-fronted, `https://opencode.ai/zen/v1`) connections from inside a
NemoClaw sandbox fail 100% of the time with a TLS reset on the proxy's re-originated (MITM)
connection. This is independent of the `protocol: rest` vs `access: full` policy setting —
switching to `access: full` did NOT stop the interception; the OCSF log still shows the
decrypted request path afterward, meaning `access: full` only lifts L7 path restrictions,
it does not provide a raw CONNECT passthrough. A normal client (host-side curl) reaches the
same Cloudflare IP successfully at the same time, so the origin itself is reachable; only the
proxy's own re-originated TLS handshake is being reset.
### Description
Chat completions sent from inside a sandbox to an OpenAI-compatible HTTPS endpoint fronted by
Cloudflare fail every time with:
APIConnectionError: Connection error.
This happens regardless of retries (3/3 always fail) and regardless of whether the sandbox's
network policy for the endpoint is `protocol: rest` (with explicit path rules) or `access: full`.
### Reproduction Steps
1. Add a sandbox network policy preset allowing `:443`, either as
`protocol: rest` with explicit method/path rules, or as `access: full`.
2. Apply it: `nemoclaw policy-add --yes`.
3. Point a `compatible`/canonical provider at the host and attempt a completion via the
official path: `nemoclaw exec -- hermes -z "test" --provider -m `.
4. Observe: 3/3 retries fail with `Connection error.`
5. Compare: from the WSL/Docker host (outside the sandbox), `curl` to the same hostname
(confirmed to resolve to the same Cloudflare IP range as the sandbox) succeeds 100% of
the time, ~0.2–0.4s TLS handshake, HTTP 200.
6. Change the policy endpoint from `protocol: rest` (+ rules) to `access: full`, re-apply via
`policy-remove` then `policy-add` (policy-add alone reports "already applied" and does not
pick up the file change). Re-run step 3. Behavior is unchanged — still fails, and the OCSF
log still shows the decrypted HTTP path, confirming TLS is still intercepted under
`access: full`.
7. Revert the policy to its original form.
### Environment
- nemoclaw v0.0.79, openshell 0.0.72
- `openshell` / `openshell-gateway` / `openshell-sandbox` binaries: mtime 2026-07-11 09:58,
unchanged across the whole period the symptom appeared (not a regression from an update)
- Sandbox network policy engine (OpenShell-managed egress proxy at the sandbox's internal
gateway address, `10.200.0.1:3128` in our environment)
### Debug Output
Host-side curl to the same Cloudflare IP range at the same time, 3 consecutive attempts:
try1: HTTP=200 tls=0.210639s total=0.451434s
try2: HTTP=200 tls=0.196017s total=0.355001s
try3: HTTP=200 tls=0.195918s total=0.356174s
DNS resolution identical from host and from inside the sandbox container (same Cloudflare
IPv6 range, `2606:4700:78::...`) — ruling out DNS-based divergence.
Policy diff test: the endpoint's policy block, byte-compared between a version known to work
previously and the currently-failing version, was **byte-identical** (`protocol: rest` +
path rules unchanged) — ruling out a policy regression as the cause. Other hosts behind the
same `protocol: rest` L7-inspection engine on the same sandbox (unrelated to this endpoint)
succeed reliably through the same proxy at the same time, ruling out the proxy being globally
broken or `protocol: rest` itself being the cause.
### Logs
```shell
## Logs
OCSF audit log for each failing attempt (sandbox-side, via the official `nemoclaw
logs` command — NOT `docker exec`, which produces misleading results for this kind of test):
NET:OPEN [INFO] ALLOWED -> :443 [policy: engine:opa]
HTTP:POST [INFO] ALLOWED POST http://:443/ [engine:l7]
NET:FAIL [LOW] :443
Underlying transport error surfaced in the agent log:
Proxy connection error: Connection reset by peer (os error 104)
Reproduced identically 6/6 times across two separate test sessions, one day apart.
```
### Checklist
- [x] I confirmed this bug is reproducible
- [x] I searched existing issues and this is not a duplicate
Contributor guide
Assessment
This issue has not been assessed yet.