ZeroClaw

ZeroClaw makes private downloads an explicit exception

ZeroClaw proposes an opt-in private-host allowlist for its file-download SSRF gate, while chat WebSocket keepalives and bidirectional JSON-RPC routing tighten long-lived transport behavior. The cluster makes network reachability and response ownership explicit instead of accidental.

← Back to homeOriginal source ↗

zeroclaw-labs/zeroclaw PR #8713 is the inspected primary source: “fix(tools): add allowed_private_hosts opt-in to file_download SSRF gate.” The related records below were inspected as supporting context rather than independent confirmation.

The facts

- zeroclaw-labs/zeroclaw PR #8713 was created 2026-07-04T14:36:24Z and was open at inspection; its title is “fix(tools): add allowed_private_hosts opt-in to file_download SSRF gate.” - zeroclaw-labs/zeroclaw PR #9701 was created 2026-08-03T14:40:12Z and was closed at inspection; its title is “feat(gateway): keep chat WebSockets alive.” - zeroclaw-labs/zeroclaw PR #8902 was created 2026-07-09T12:46:31Z and was closed at inspection; its title is “fix(runtime): route bidirectional JSON-RPC responses.” - The repository reported 32564 stars, 712 open issues, default branch master, and last push 2026-08-13T01:00:27Z. - The latest tagged-release baseline checked was v0.8.4 published 2026-08-02T21:00:00Z.

What changed

zeroclaw-labs/zeroclaw PR #8713 reports: Summary **Base branch:** master **What changed and why:** The operator-configured [file_download].url was fetched without any SSRF validation, so a typo or copy-paste of http://127.0.0.1, http://169.254.169.254/latest/meta-data/, or http://10.0.0.5/... would silently route to loopback, cloud metadata, or an internal admin panel. The URL is now gated at dispatch time and the validated address set is bound into the reqwest client via resolve_to_addrs, so a second unbound DNS lookup at connect time cannot bypass the gate. The gate separates the policy hostname (canonical, trailing dot stripped, used for allowlist comparison) from the exact transport hostname (used for the resolve_to_addrs key). The SSRF preflight resolves the exact transport hostname — preserving the terminal DNS dot — so the validated address set is pinned to the absolute name the request connects to and resolver search-list behavior cannot substitute a different relative name. policy_host is retained only for allowlist comparison and diagnostics. Local authorization, required-argument, and destination validation all run before any DNS I/O. An injected counting resolver proves each local rejection path performs zero resolver calls. allowed_private_hosts is an operator

zeroclaw-labs/zeroclaw PR #9701 reports: Summary **Base branch:** master **What changed and why:** Add [gateway].websocket_ping_interval_secs for configuring Web UI chat WebSocket keepalive pings. Send server-side WebSocket Ping frames during idle connections and while agent turns are streaming, preventing intermediary timeouts during long-running chats. Respond to incoming WebSocket Ping frames with Pong frames. Default the interval to 30 seconds; setting it to 0 disables server-side keepalive pings. **Scope boundary:** This changes only the gateway Web UI chat WebSocket (/ws/chat); it does not alter ACP, SOP-runs, channel WebSockets, or frontend application-level message formats. **Blast radius:** Gateway chat WebSocket connections and the typed [gateway] configuration schema. Existing configurations receive the 30-second default; WebSocket control frames are handled without affecting chat messages. **Linked issue(s):** Related #9002 (complementary disconnect-survival work; neither PR depends on the other). **Labels:** enhancement, dependencies, config, gateway, dev, trusted contributor, risk:high, size:S Testing (required) How you can test **Reviewer testing requested?** Yes **Interface(s) exercised:** web surface, wss channel (/ws/chat) **Setup / preconditions:** Run ZeroClaw with the Web UI gateway and a configured agent. Set [gateway].websocket_ping_interval_secs = 5 in the config for

zeroclaw-labs/zeroclaw PR #8902 reports: Summary **Base branch:** master (all contributions) **What changed and why:** Route valid JSON-RPC success, error, and explicit-null responses to the daemon's pending outbound caller so ZeroCode ask-user and poll interactions can complete. Validate request, notification, and response envelopes at the shared RPC boundary instead of silently dropping valid JSON with an invalid JSON-RPC shape. Document daemon-originated requests, directional response correlation, and failure behavior for the local socket transport. **Scope boundary:** No ZeroCode UI code or interaction semantics, config, durable state, dependency direction, or ID scheme changed. ZeroCode keeps its existing independent wire model; the observable fix is that its existing ask-user and poll responses now complete the daemon's pending calls. **Blast radius:** The local daemon RPC dispatcher and shared JSON-RPC types. RpcOutbound remains the sole pending-response owner. **Linked issue(s):** Related #9010. Duplicate implementation #8315 is closed. **Labels:** bug, docs, runtime, needs-author-action, stale-candidate, risk:high, size:M. Testing (required) How you can test (when useful) **Reviewer testing requested?** Yes; a real ask-user or poll turn adds useful process-boundary evidence beyond the deterministic dispatcher tests. **Interface(s) exercised:** surface: tui,

Why it matters

Private downloads can be legitimate, but a blanket exception turns an SSRF defense into decoration. Long-lived sockets and reverse JSON-RPC responses also need clear ownership when connections churn. The operator test is whether visible output, retained state and authority still describe the same event after retries, background work or restart.

Current

The primary record was open when captured on 2026-08-13. The tagged-release baseline was v0.8.4 published 2026-08-02T21:00:00Z. Repository metadata, full source bodies, current pull requests and issues, releases, Google News, Hacker News, Lobsters, Metamesh and the rendered ClawCharts row were inspected. ClawCharts selected the subject; it did not prove the claim.

Evidence

The primary URL is https://github.com/zeroclaw-labs/zeroclaw/pull/8713. Supporting records are https://github.com/zeroclaw-labs/zeroclaw/pull/9701 and https://github.com/zeroclaw-labs/zeroclaw/pull/8902. Source bodies, timestamps and states are preserved in the daily evidence bundle. Test counts and reproductions remain attributed to their authors unless identified as independently rerun.

Source boundary

Open work is described as open, closed work as closed, and operator reports as reports. A pull request is evidence of proposed or reviewed direction, not proof of a shipped release. Search residue, package mirrors and historically published source spines were excluded.

Operator take

Scope private-host exceptions narrowly, log effective destinations without secrets, and bind every response and keepalive to the connection generation that owns it. Preserve a before-state receipt, make the smallest reversible change, and verify the original failure independently.

Caveat

Public project records are mutable. Status, scope and evidence can change after publication. This brief records the inspected state and does not authorize changes to a reader’s deployment.

Source inspected; source state, environment and release boundary remain explicit.