Listener startup failure via unbracketed IPv6 bind-address formatting

    • Type: Task
    • Resolution: Unresolved
    • Priority: Trivial - P5
    • None
    • Affects Version/s: None
    • Component/s: None
    • Monguard
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      If an operator configures an IPv6 bind address, that listener may fail to start; this only hurts the operator's own deployment.

      Impact

      The affected listener fails to start (or the process errors out at bootstrap) when an IPv6 bind address is configured — a self-inflicted, recoverable availability loss for the operator's own deployment.
      Severity: low
      Exploitability: theoretical — Trivially reproducible by the operator, but there is no external attacker — the only party who can set the value is the same party harmed by the failure, and they already control service availability.

      Location

      • monguard/src/config/validated.rs:252 in ListenerPort::listen_addr
      • monguard/src/listeners/mod.rs:106 in build_listeners
      • monguard/src/listeners/mod.rs:112 in build_listeners
      • monguard/src/config/resolver.rs:810 in resolve_listener_port
      • monguard/src/config/resolver.rs:869 in resolve_bind_address

      Reproduction / trigger path

      Analyzed trigger path from static analysis — not an executed PoC. Confirm with a concrete repro before handing off.

      Attacker controls: Operator fully controls the YAML `listeners.address` / `listeners.ports[].address` string; no remote or lower-privileged input reaches this field.

      1. (source) monguard/src/config/loader.rs:27 in load_config — Operator-authored YAML config file is read from local disk via std::fs::read_to_string(&cli.config).
      2. (hop) monguard/src/config/resolver.rs:810 in resolve_listener_port — Per-port address string parsed with IpAddr::from_str — accepts IPv6 literals and stores IpAddr::V6.
      3. (hop) monguard/src/config/resolver.rs:869 in resolve_bind_address — Listeners-level default address likewise parsed with IpAddr::from_str — accepts IPv6.
      4. (hop) monguard/src/config/validated.rs:252 in ListenerPort::listen_addr — format!("{}:{}", self.address, self.port) renders IPv6 without brackets.
      5. (hop) monguard/src/main.rs:303 in MonguardServer::run (listener loop) — build_listener_service is invoked once per configured port at process startup.
      6. (hop) monguard/src/listeners/mod.rs:36 in build_listener_service — proxy_bind = port.listen_addr() — unbracketed string captured.
      7. (sink) monguard/src/listeners/mod.rs:112 in build_listeners — listeners.add_tcp_with_settings(bind_addr, ...) (and :106 for TLS) hands the malformed string to Pingora, which fails the socket-address parse/bind.

      Root cause

      • `ListenerPort.address` is typed `IpAddr` and admits IPv6 values (monguard/src/config/validated.rs:238); the resolver accepts IPv6 literals via `IpAddr::from_str` with no v4-only guard (monguard/src/config/resolver.rs:810, :869).
      • `listen_addr()` formats with `format!("{}:{}", self.address, self.port)` (monguard/src/config/validated.rs:252); `IpAddr::V6`'s `Display` impl emits e.g. `::1` without square brackets, producing `::1:27017`.
      • `build_listener_service` passes this string verbatim to Pingora's `add_tls_with_settings` / `add_tcp_with_settings` (monguard/src/listeners/mod.rs:36, :106, :112), which later parses it as a socket address when binding.
      • Standard `SocketAddr` parsing rejects unbracketed IPv6 host:port strings, so the listener bind fails at startup.

      Filed from Aegis finding 780a21ba934e (scan scan-3c7821728fe9) · primitive: Operator-authored IPv6 bind address is rendered without brackets, yielding an unparseable bind string at service startup. · categories: Crash, Other

            Assignee:
            Unassigned
            Reporter:
            Anand Paithankar
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: