-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The current ManagedWebSocket.IsValidCloseStatus implementation may reject certain valid status codes when it shouldn't #82602
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsI don't have a clean code snippet for this (suspected) bug but the current implementation of Suppose we have client-side code as follows, and WS server closes WebSocket proactively after a while, with status code 1014 using var wsClient = new ClientWebSocket();
await wsClient.ConnectAsync(new Uri("..."), default);
var result = await wsClient.ReceiveAsync(Memory<byte>.Empty, default); There will be an Exception thrown from client side,
It seems that currently I think the point is, as long as the WS close frame received from remote-side is valid, is it possible for runtime/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs Lines 1030 to 1067 in 5415cd1
|
I see that these codes (1012, 1013, 1014) are reserved, but not a part of any official RFC yet... I wonder what is our policy for such cases @stephentoub @dotnet/ncl The problem IMO is not only that it throws, but it also loses the information about the actual close status and everything that was in the close frame runtime/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs Lines 984 to 987 in 57bfe47
Also, we can send 1014&co but can't receive it -- the checks for received close status and for to-be-sent close status are different, which is additionally troublesome. |
Triage: we decided that we will allow the reserved codes (1012, 1013, 1014), but we won't add them to the WebSocketCloseStatus enum, unless there would be much customer ask. This way we won't need to change public API. The fix should be straightforward. We are happy to accept contributions. Putting to Future, since it's the first issue about it in quite a long time. |
In building out the tests for this it becomes evident that not adding the three new acceptable close status codes to the Additionally, while the RFC doesn't spell these codes out, the Mozilla doc does and they are reasonably likely to never be usurped. |
Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of `WebSocketCloseStatus` values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard\ the status description. Fixes dotnet#82602
Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of `WebSocketCloseStatus` values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard the status description. Fixes dotnet#82602
Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of `WebSocketCloseStatus` values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard the status description. Fixes dotnet#82602
PR #83713 (sorry for the mess above... just trying to neaten up the commit comment and broke everything, Mea Culpa) |
How exactly does it break testing? (let's move the conversation to your PR though, I've put some comments there) |
I'm reworking this now per the feedback on the PR |
Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of `WebSocketCloseStatus` values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard the status description by adding them to the private `IsValueCloseStatus` method switch statement declaring them as valid `true`. These codes are documented [here as IANA registered codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code) as valid server-initiated close reasons. Fixes Issue dotnet#82602
* Allow non RFC close statuses in ManagedWebSocket Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of `WebSocketCloseStatus` values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard the status description by adding them to the private `IsValueCloseStatus` method switch statement declaring them as valid `true`. These codes are documented [here as IANA registered codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code) as valid server-initiated close reasons. Fixes Issue #82602 * Cleanup comment format Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com> * Rename test data to CloseStatuses Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com> * Rename test method to follow naming convention. Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com> * Addressed PR feedback Finished rename of CloseStatuses test data Renamed `closeStatusDescription` to `serverMessage` Send hello message and close status then await both responses and check they are as expected. This necessitated switching to the `ReceiveAsync` that accepts an `ArraySegment`. Explicitly typed `var`s Inlined helper methods (for clarity) * Rename local for per PR feedback Swapping back to a distinct and more appropriately named variable for the `closeStatusDescription` Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com> * Label the boolean for isServer flag Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com> * Use better local variable name Renamed local `serverMessage` back to `closeStatusDescription` per PR feedback. Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com> * Address PR and rebase to main Rebased to current main, updated the commit messages and added the remaining changes to address the PR comments. --------- Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com> Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com>
I don't have a clean code snippet for this (suspected) bug but the current implementation of
IsValidCloseStatus
will reject WebSocket close status code 1014 "Bad Gateway". Specifically, if remote-side initiates WS closure with status code 1014,ManagedWebSocket
will immediately abort the connection.Suppose we have client-side code as follows, and WS server closes WebSocket proactively after a while, with status code 1014
There will be an Exception thrown from client side,
wsClient
entersAborted
state, and server-side also observes the client-side has aborted connection instead of replying with a Close handshake message.It seems that currently
ManagedWebSocket.IsValidCloseStatus
will reject all the WS close status code falling into the range of 1000-2999 but not within the (most of the)WebSocketCloseStatus
enum values. This is too strict and not resilient to any possible future extensions.I think the point is, as long as the WS close frame received from remote-side is valid, is it possible for
ManagedWebSocket
just to relay whatever status code received from remote side to the API consumer, and let them decide whether they'd like to abort the connection? I understand there are some status codes never intended to be sent (e.g., 1005 "Empty" or 1006 "Abnormal closure"), but that doesn't sound fit to me to reject all the other status codes in 1000-2999 because of this.runtime/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs
Lines 1030 to 1067 in 5415cd1
The text was updated successfully, but these errors were encountered: