fix(sandbox): add managed loopback proxy#1501
Conversation
|
@ericksoa I see this maps back to something for Discord in NemoClaw but can you expand on the requirement a bit more and the use case? |
|
Good question. The OpenShell requirement here is not Discord-specific; Discord/OpenClaw is just the first concrete client that exposed the gap. The generic use case is: a sandboxed app or SDK needs to use an HTTP CONNECT proxy, but the app will only accept a loopback proxy URL such as The Discord case is a good example because OpenClaw's Discord Gateway client ignores So the intended OpenShell contract is:
That gives clients with strict localhost proxy requirements a standard OpenShell affordance, while keeping the security boundary and protocol handling in one place. |
|
For the concrete downstream context, the dependent NemoClaw PR is NVIDIA/NemoClaw#4005: NVIDIA/NemoClaw#4005 That PR consumes this OpenShell affordance by preferring |
|
Ok, understood on the use case. So the listener is placed on the sandbox loopback but then after The better impl is to keep only the loopback listener in the sandbox network namespace and then hand the accepted client socket back to code that's running in the supervisor network namesapce before DNS, policy handling, cred rewrite and upstream dialing. |
Summary
OPENSHELL_LOOPBACK_PROXY_URL.127.0.0.1:3128, for clients that require a loopback proxy URL.HTTP_PROXY/HTTPS_PROXYbehavior unchanged for ordinary proxy-aware clients.Methodology
Findings Incorporated
OPENSHELL_LOOPBACK_PROXY_URLso existing proxy env behavior stays compatible.Combined Validation
18080, dashboard port18889, unique Docker network, and unique OpenShell Docker sandbox namespace.083c0663187a3e93e60cd4d32b30053475cb0890,openshell 0.0.47-dev.3+gb75abad.dd022b578806aa3880b33ac2c3fe6a86f230ff33.openshell-sandboxbuilt from this OpenShell PR and mounted through[openshell.drivers.docker].supervisor_bin.M9bbakedhttp://127.0.0.1:3128into OpenClaw Discord config,M13d-configconnected to the fake Discord Gateway using the proxy URL fromopenclaw.json,M13dcompleted the native WebSocket upgrade,M13fproved the fake Gateway received the host-side Discord token while the sandbox-visibleIDENTIFYcarried only the placeholder, andM13gproved an unregistered placeholder fails closed.S1, an existing Slack guard probe that hardcodes internal port18789; this isolated run intentionally usedNEMOCLAW_DASHBOARD_PORT=18889to avoid a local port collision. That failure is outside the Discord loopback/WebSocket credential-rewrite path andS2still proved the Slack guard caughtinvalid_authwithout crashing the gateway.References Considered
Test Plan
cargo fmtcargo fmt --all -- --checkgit diff --checkcargo check -p openshell-sandboxcargo clippy -p openshell-core -p openshell-sandbox --all-targets -- -D warningscargo clippy --workspace --all-targets -- -D warningscargo clippy --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warningscargo test -p openshell-sandbox apply_loopback_proxy_env_exposes_managed_url_without_changing_proxy_vars --libcargo test -p openshell-sandbox websocket --libcargo test -p openshell-sandbox --test websocket_upgradeM9b,M13d-config,M13d,M13f,M13gpassed using the OpenClaw Discord account proxy from generated config.Note:
mise run rust:format:check/mise run rust:lintare blocked locally because this checkout'smise.tomlis not trusted on the machine, so the underlying task commands above were run directly.