Problem
ExposureMode.Local defaults Daemon.Host to 127.0.0.1, but nothing prevents a user from setting it to 0.0.0.0 or a LAN IP. When they do:
- The daemon listens on all interfaces (or a specific non-loopback address)
LoopbackAuthenticationHandler correctly returns NoResult for non-loopback connections — they don't get auto-operator trust
- But if no device is paired and no other auth scheme is configured, those unauthenticated requests simply fall through with no identity
The exposure validation in DaemonExposureValidator.Validate() skips all checks when ExposureMode doesn't require remote authentication (line 127-128), so Local mode with a non-loopback bind is an unvalidated combination.
This is a different gap from #866 (reverse-proxy operator access) and #868 (transport/auth decoupling) — it's simpler and narrower: a user can accidentally expose the daemon on a network interface without realizing that Local mode doesn't enforce loopback-only binding.
Proposed fix
Add a startup validation warning (or error) when ExposureMode.Local and Host resolves to a non-loopback address. Something like:
Daemon.Host is set to '0.0.0.0' but ExposureMode is 'local'. Remote connections will not have operator access. To serve remote traffic, set Daemon.ExposureMode to configure remote authentication.
This should be surfaced both at daemon startup and via netclaw doctor.
Acceptance criteria
DaemonExposureValidator.Validate() produces a warning-level issue when ExposureMode.Local and Host is non-loopback
ExposureModeValidationService logs the warning at startup
ExposureModeDoctorCheck surfaces it during netclaw doctor
- Existing tests for Local mode with loopback Host are unaffected
- New test covers Local mode +
0.0.0.0 producing the expected validation issue
Related issues
Problem
ExposureMode.LocaldefaultsDaemon.Hostto127.0.0.1, but nothing prevents a user from setting it to0.0.0.0or a LAN IP. When they do:LoopbackAuthenticationHandlercorrectly returnsNoResultfor non-loopback connections — they don't get auto-operator trustThe exposure validation in
DaemonExposureValidator.Validate()skips all checks whenExposureModedoesn't require remote authentication (line 127-128), so Local mode with a non-loopback bind is an unvalidated combination.This is a different gap from #866 (reverse-proxy operator access) and #868 (transport/auth decoupling) — it's simpler and narrower: a user can accidentally expose the daemon on a network interface without realizing that Local mode doesn't enforce loopback-only binding.
Proposed fix
Add a startup validation warning (or error) when
ExposureMode.LocalandHostresolves to a non-loopback address. Something like:This should be surfaced both at daemon startup and via
netclaw doctor.Acceptance criteria
DaemonExposureValidator.Validate()produces a warning-level issue whenExposureMode.LocalandHostis non-loopbackExposureModeValidationServicelogs the warning at startupExposureModeDoctorChecksurfaces it duringnetclaw doctor0.0.0.0producing the expected validation issueRelated issues
/tmp/netclawas thewwwrootseems like a bad idea #189