Skip to content

fix(control): pin control-client to direct loopback + CONTROL_METHODS/dispatch lockstep guard (#711)#49

Merged
MichaelTaylor3d merged 2 commits into
mainfrom
fix/control-client-noproxy-lockstep
Jul 17, 2026
Merged

fix(control): pin control-client to direct loopback + CONTROL_METHODS/dispatch lockstep guard (#711)#49
MichaelTaylor3d merged 2 commits into
mainfrom
fix/control-client-noproxy-lockstep

Conversation

@MichaelTaylor3d

@MichaelTaylor3d MichaelTaylor3d commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Closes DIG-Network/dig_ecosystem#711.

What changed

Two dig-node control-client hardening follow-ups from the #45 CLI-parity gates (both defense-in-depth; neither blocked #45).

  1. no_proxy pin (control_client.rs). The operator loopback control client now builds its reqwest client via build_control_client() with .no_proxy(). reqwest's default env-proxy behaviour has NO automatic loopback bypass, so a hostile HTTP_PROXY/HTTPS_PROXY could route the token-bearing control.* POST (carrying the master control token) through an attacker proxy. The transport is now pinned DIRECT to 127.0.0.1/::1. (server.rs's http client is the OUTBOUND upstream/rpc.dig.net client, not a control client — correctly left proxy-honoring.)
  2. CONTROL_METHODSdispatch_control lockstep (control.rs). dispatch_control now routes owned methods via a new OWNED_CONTROL_METHODS routing const (delegating the rest to the node's control surface); the owned match's _ arm is unreachable! by construction. A new test control_methods_partition_into_owned_and_delegated asserts CONTROL_METHODS equals OWNED_CONTROL_METHODSDELEGATED_CONTROL_METHODS exactly (disjoint union), closing the shell-owned-method drift gap the existing cli_covers_every_node_control_method test leaves open.

Blast radius (gitnexus + grep)

build_control_client/call_async (control_client.rs) — only caller is call_control (the CLI control path); no behaviour change beyond proxy-pinning. dispatch_control (control.rs) — refactor is behaviour-preserving (same owned arms, same delegation); CONTROL_METHODS public const unchanged (consumed by control_cli.rs drift test + dig-browser controller). No wire/API change.

Tests (TDD, both RED-verified)

  • control_client::tests::control_client_ignores_http_proxy_and_connects_direct — RED without .no_proxy() (dialed the dead proxy 127.0.0.1:9).
  • control::tests::control_methods_partition_into_owned_and_delegated — RED with an injected OWNED drift entry.

Gates

fmt --check clean · clippy -D warnings clean · full dig-node-service lib suite 213 passed. (Path-length MAX_PATH forces a redirected CARGO_TARGET_DIR; CI unaffected.)

Version

0.38.10.38.2patch: defense-in-depth hardening + a test; no public-API or behaviour change to the shipped surface. Apps/nightlies → rides the next nightly; stable is manual.

Refs #426 #501.

🤖 Generated with Claude Code

MichaelTaylor3d and others added 2 commits July 17, 2026 04:43
Co-Authored-By: Claude <noreply@anthropic.com>
…the control method table (#711)

Two control-plane hardening follow-ups from the #45 CLI-parity gates:

1. no_proxy pin: the operator loopback control client now builds its reqwest
   client with `.no_proxy()`, so a hostile `HTTP_PROXY`/`HTTPS_PROXY` in the
   environment can no longer route the token-bearing `control.*` POST through
   an attacker-controlled proxy. reqwest's default proxy behaviour has no
   automatic loopback bypass; the control plane is loopback-only + token-gated,
   so the transport is now pinned DIRECT to 127.0.0.1/::1.

2. CONTROL_METHODS <-> dispatch_control lockstep: dispatch_control now routes
   owned methods via the new OWNED_CONTROL_METHODS routing const (delegating
   the rest to the node), and a lockstep test asserts CONTROL_METHODS equals
   OWNED_CONTROL_METHODS + DELEGATED_CONTROL_METHODS exactly (disjoint union).
   This closes the shell-owned-method drift gap the cli_covers_* test leaves
   open. The owned match's `_` arm is unreachable by construction.

TDD: both tests verified RED first (proxy test dialed the dead proxy; partition
test caught an injected drift entry). fmt + clippy -D + full lib suite (213)
green. Version bumped 0.38.1 -> 0.38.2 (patch: defense-in-depth hardening, no
public-API or behaviour change to the shipped surface). SPEC §7.3 updated.

Refs #426 #501
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d marked this pull request as ready for review July 17, 2026 12:03
@MichaelTaylor3d
MichaelTaylor3d merged commit 4e5a465 into main Jul 17, 2026
14 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the fix/control-client-noproxy-lockstep branch July 17, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant