httpserver: restrict /websocket/raw to localhost - #3760
Conversation
Fix two bugs in DroneCAN.GetParameters() that caused parameter enumeration to stop before retrieving all parameters: 1. SemaphoreSlim(1) allowed the while loop to send duplicate GetSet requests before receiving responses. When both duplicate responses arrived, the index was incremented twice, skipping intermediate parameter indices. Changed to SemaphoreSlim(0) so the loop blocks until each response arrives. 2. Message filter used a single AND condition that failed to filter out service messages from wrong nodes. A stray GetSet_res with name_len==0 from another node could trigger premature end-of-enumeration. Fixed to use two separate conditions matching the proven pattern in SetParameter().
The /websocket/raw WebSocket endpoint accepts unauthenticated connections from any network interface, allowing remote hosts to inject arbitrary MAVLink commands into the active vehicle link. Add an IPAddress.IsLoopback() check on the TCP remote endpoint before completing the WebSocket handshake, consistent with the existing protections on /guided? and POST /guide. Fixes ArduPilot#3757
fallenmi
left a comment
There was a problem hiding this comment.
I verified that the new guard runs before the WebSocket 101 response and before the raw bridge is installed in both the desktop and Xamarin copies. A socket-level oracle using the same TcpClient.Client.RemoteEndPoint / IPAddress.IsLoopback path sees 127.0.0.1 as loopback and a connection through the host's non-loopback interface as non-loopback, so the latter takes the fail-closed 403 path while the built-in local clients remain allowed. A missing or non-IP endpoint is also rejected.
The net PR diff is limited to these two matching guards. Release, Debug, macOS, and iOS builds are green. The two Android failures are baseline infrastructure failures: exact current base 67a3c4f and this head both fail because the VS18 runner lacks Xamarin.Android.CSharp.targets, with the same MSB4226 error.
This closes the unauthenticated remote-command path without changing the local WebSocket protocol. Looks good to me.
Disclosure: I used OpenAI Codex to inspect the exact head/base, verify the socket address classification, and compare the CI failures; I verified the result.
Fixes #3757
The /websocket/raw WebSocket endpoint on TCP/56781 accepts unauthenticated connections from any network interface. Remote hosts can inject arbitrary MAVLink commands into the active vehicle link — for example, changing the flight mode of a disarmed drone.
This adds an IPAddress.IsLoopback() check on the TCP remote endpoint before completing the WebSocket handshake, consistent with the existing protections on /guided? and POST /guide (added in ec2b6fc and 980d2b8).
Applied to both the desktop server (Utilities/httpserver.cs) and the Xamarin copy (ExtLibs/Xamarin/Xamarin/Linked/httpserver.cs).
All built-in clients (WASM, HUD, Blazor) connect to localhost and are unaffected.