2.6 KiB
ADR-296: Sensor data-plane hardening — UDP bind control and source allowlist (step one)
- Status: Accepted — initial implementation (this PR)
- Date: 2026-08-11
- Deciders: ruv
- Tags: security, udp, sensor-ingest, sensing-server
Context
The CSI UDP receiver binds 0.0.0.0:{udp_port} unconditionally
(main.rs:5706), with no equivalent of the HTTP --bind-addr flag (which
correctly defaults to 127.0.0.1), no source allowlist, no message
authentication, no device identity, and no replay defense. Any host that can
reach the UDP port can inject a valid-shaped frame, flip an auto-detecting
server into a live source state, and influence presence/vital/automation
outputs (issue 1394).
An IP allowlist does not stop LAN spoofing, but bind control plus an allowlist is the correct, shippable first step; per-device keys + authenticated encryption + monotonic sequence + freshness window + replay rejection is the full fix and is larger.
Decision
This PR (step one):
- Add
--udp-bind(envRUVIEW_UDP_BIND), defaulting to127.0.0.1. Binding to a routable address is now an explicit operator choice, mirroring the HTTP path. Desktop/appliance defaults stay loopback. - Add an optional source IP/CIDR allowlist (
--udp-allow); when set, frames from other sources are dropped and counted. Loopback is always allowed. - Emit a startup security log line stating the bind scope and whether an
allowlist is active; refuse a routable bind without an allowlist unless an
explicit
--udp-insecure-lanoverride is passed (parallel to the existing Docker HTTP refusal). - Publish a
SECURITY.md/advisory note describing the threat model and safe deployment.
Explicitly deferred to a follow-up ADR (step two): per-device provisioned keys, MAC/AEAD, device identifiers, monotonic sequence numbers, freshness window, and replay rejection. This ADR documents that gap rather than implying the data plane is authenticated.
Consequences
- Removes the default open-to-LAN exposure with a one-line-safe default.
- Not spoof-proof on a trusted LAN — the advisory says so plainly, and the
override name (
--udp-insecure-lan) makes the residual risk legible. - A behavior change for anyone relying on the old implicit
0.0.0.0default; called out in the changelog and the startup log.
Validation
- Unit tests: default bind is loopback; routable bind without allowlist is refused unless overridden; allowlist accept/drop with counting; loopback always allowed.
cargo test -p wifi-densepose-sensing-server.- Real-silicon validation of the LAN path remains required before any deployment claim.