Skip to content

Reject an initial map without a valid self node instead of installing a zero identity #127

Description

@forkwright

Finding

The first non-keepalive MapResponse initializes Netmap even when the control server omits this machine's Node or supplies one that fails key/routing validation. Instead of returning an error or leaving the client uninitialized, Netmap::from_full_response manufactures a zero-value node with ID 0, empty key, empty name, and no routing data.

Later malformed self-node deltas are rejected while preserving the prior valid identity. The initial path therefore has a uniquely weaker contract: malformed identity becomes successful initialization.

Verified against main 9aa9a56223afdd47d7723104cd16a5c07d5fc722.

Evidence

  • crates/dictyon/src/control/netmap.rs:47-67 filters the initial resp.node through node_is_valid, then calls unwrap_or_else(zero_value_node) for both absent and invalid values.
  • netmap.rs:229-247 constructs that fallback with id: 0, an empty node key and name, empty addresses, and no endpoint, DERP, disco-key, or expiry state.
  • netmap.rs:92-99 treats later malformed resp.node values differently: it warns and preserves the existing self node rather than installing a fabricated replacement.
  • crates/dictyon/src/control/mod.rs:384-403 makes first-response initialization infallible: apply_map_response returns () and stores Netmap::from_full_response(resp). recv_map_update at :294-312 consequently reports Ok(false) after accepting the fabricated identity.
  • control/mod.rs:414-417 exposes self_node() as Some(&Node) whenever the netmap exists, so callers cannot distinguish a real self record from the placeholder by the option state.
  • The regression test at crates/dictyon/src/control/tests/netmap_tests.rs:400-424 explicitly locks this behavior: a malformed self key must still initialize the netmap and produce self_node.key == "".
  • No current issue owns the initial-self identity failure. Audit (WAVE 1): 14 low/info findings — dictyon + hamma-core (judge-upheld) #55's closed validation work rejects malformed peer and routing inputs but retained this synthetic-success path.

Why this matters

The self node is the local identity and routing anchor for every later stage: assigned addresses, capability level, key expiry, endpoint publication, and eventual data-plane configuration. A zero-value record is not a degraded but meaningful identity; it is the absence of identity represented as success.

Downstream code can therefore observe “netmap initialized” and Some(self_node) while operating on ID 0 and an empty key. That allows later state transitions, UI/status reporting, persistence, or data-plane preparation to proceed from a condition that should have blocked initialization.

The fallback also hides protocol regressions. A reference-server field omission or a validation rule that becomes too strict produces a warning and synthetic state instead of a testable interoperability failure.

Desired correction

Make initial netmap construction fallible and require one valid self node before publishing initialized state. An absent or malformed initial Node should return a typed control/netmap error and leave the previous state unchanged; on a client with no previous state, self_node() must remain None.

Keep delta semantics distinct: a malformed later self update may be ignored while preserving a previously validated identity, with an observable warning/metric.

Done when:

  • Netmap::from_full_response returns a Result or equivalent validated domain type;
  • absent and malformed initial self nodes fail the map update without creating a netmap;
  • recv_map_update propagates the typed failure rather than returning successful modification;
  • no production zero_value_node identity remains;
  • malformed later deltas preserve an existing valid self node; and
  • tests cover absent initial self, malformed initial self, valid initialization, and malformed post-initialization updates.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or production defectseverity:highSignificant breakage with no available workaround

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions