diff --git a/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx index 3ddd42906a160c..501137ffe613ff 100644 --- a/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx @@ -117,6 +117,9 @@ The WebSocket server sent a masked frame. + + The WebSocket client sent an unmasked frame. + The WebSocket received a continuation frame from a previous final message. diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs index 4e3a261e1ecb77..553a254c2770d4 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs @@ -1349,6 +1349,11 @@ private async ValueTask CloseWithReceiveErrorAndThrowAsync( // Consume the mask bytes ConsumeFromBuffer(4); } + else if (_isServer) + { + resultHeader = default; + return SR.net_Websockets_ServerReceivedUnmaskedFrame; + } // Do basic validation of the header switch (header.Opcode) diff --git a/src/libraries/System.Net.WebSockets/tests/WebSocketTests.cs b/src/libraries/System.Net.WebSockets/tests/WebSocketTests.cs index 73e84998a94197..41c7fe341d266d 100644 --- a/src/libraries/System.Net.WebSockets/tests/WebSocketTests.cs +++ b/src/libraries/System.Net.WebSockets/tests/WebSocketTests.cs @@ -182,6 +182,20 @@ public async Task ThrowWhenContinuationWithDifferentCompressionFlags() client.SendAsync(Memory.Empty, WebSocketMessageType.Binary, WebSocketMessageFlags.EndOfMessage, default)); } + [Fact] + public async Task ReceiveAsync_ServerUnmaskedFrame_ThrowsWebSocketException() + { + byte[] frame = { 0x81, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F }; + using var stream = new MemoryStream(); + stream.Write(frame, 0, frame.Length); + stream.Position = 0; + using WebSocket websocket = WebSocket.CreateFromStream(stream, new WebSocketCreationOptions { IsServer = true }); + WebSocketException exception = await Assert.ThrowsAsync(() => + websocket.ReceiveAsync(new byte[5], CancellationToken.None)); + Assert.Equal(SR.net_Websockets_ServerReceivedUnmaskedFrame, exception.Message); + Assert.Equal(WebSocketState.Aborted, websocket.State); + } + [Fact] public async Task ReceiveAsync_WhenDisposedInParallel_DoesNotGetStuck() {