{"record":{"id":"04983bfa4aa0dc93","repo":"TooTallNate/Java-WebSocket","slug":"bad-rsv-rsv1-rsv1-rsv2-rsv2-rsv3-rsv3","errorCode":null,"errorMessage":"bad rsv RSV1: {rsv1} RSV2: {rsv2} RSV3: {rsv3}","messagePattern":"bad rsv RSV1: (.+?) RSV2: (.+?) RSV3: (.+?)","errorType":"exception","errorClass":"InvalidFrameException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/java_websocket/extensions/CompressionExtension.java","lineNumber":44,"sourceCode":"package org.java_websocket.extensions;\n\nimport org.java_websocket.exceptions.InvalidDataException;\nimport org.java_websocket.exceptions.InvalidFrameException;\nimport org.java_websocket.framing.ControlFrame;\nimport org.java_websocket.framing.DataFrame;\nimport org.java_websocket.framing.Framedata;\n\n/**\n * Implementation for a compression extension specified by https://tools.ietf.org/html/rfc7692\n *\n * @since 1.3.5\n */\npublic abstract class CompressionExtension extends DefaultExtension {\n\n  @Override\n  public void isFrameValid(Framedata inputFrame) throws InvalidDataException {\n    if ((inputFrame instanceof DataFrame) && (inputFrame.isRSV2() || inputFrame.isRSV3())) {\n      throw new InvalidFrameException(\n          \"bad rsv RSV1: \" + inputFrame.isRSV1() + \" RSV2: \" + inputFrame.isRSV2() + \" RSV3: \"\n              + inputFrame.isRSV3());\n    }\n    if ((inputFrame instanceof ControlFrame) && (inputFrame.isRSV1() || inputFrame.isRSV2()\n        || inputFrame.isRSV3())) {\n      throw new InvalidFrameException(\n          \"bad rsv RSV1: \" + inputFrame.isRSV1() + \" RSV2: \" + inputFrame.isRSV2() + \" RSV3: \"\n              + inputFrame.isRSV3());\n    }\n  }\n}\n","sourceCodeStart":26,"sourceCodeEnd":56,"githubUrl":"https://github.com/TooTallNate/Java-WebSocket/blob/afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d/src/main/java/org/java_websocket/extensions/CompressionExtension.java#L26-L56","documentation":"CompressionExtension.isFrameValid rejects any DATA frame (text/binary/continuation) that has RSV2 or RSV3 bits set, since only RSV1 may be used for permessage-deflate compression. Setting reserved RSV bits without a negotiated extension is a WebSocket protocol violation, so an InvalidFrameException (close code 1002, PROTOCOL_ERROR) is thrown. The message reports the state of all three RSV bits.","triggerScenarios":"A peer sends a text/binary/continuation frame with RSV2=1 or RSV3=1 while permessage-deflate (or another RSV-claiming extension) is negotiated — the extension only owns RSV1. Typically a client implementing its own (non-negotiated) compression scheme.","commonSituations":"Client enabling a proprietary compression flag on frames without offering a matching extension in the handshake; buggy/fuzzing clients setting random RSV bits; a custom extension on one side not mirrored in the server's extension negotiation.","solutions":["Fix the peer to only set RSV1 for compressed frames under permessage-deflate and leave RSV2/RSV3 = 0","If the peer needs its own compression, implement and negotiate a matching WebSocketExtension on both sides (offer it in the draft)","Verify the client library version actually negotiated the extension it is using (check Sec-WebSocket-Extensions in the handshake)","Handle close code 1002 and log the reported RSV bits to identify which bit the peer sets"],"exampleFix":"// before: client marks frames with RSV2\nframe.setRSV(true, true, false);\n// after: only RSV1 for negotiated permessage-deflate\nframe.setRSV(compressed, false, false);","handlingStrategy":"try-catch","validationCode":"// sender side: data frames may only set RSV1 when permessage-deflate is negotiated\nif (isDataFrame && (rsv2 || rsv3)) throw new IllegalStateException(\"RSV2/RSV3 must be 0 on data frames\");","typeGuard":null,"tryCatchPattern":"@Override public void onClose(int code, String reason, boolean remote) {\n  if (code == 1002 && reason.startsWith(\"bad rsv\")) { disableCompressionOnPeer(); reconnect(); }\n}","preventionTips":["Use permessage-deflate via the library's PerMessageDeflateExtension instead of hand-rolled RSV flags","Only set RSV1 for compression, and only when the extension was negotiated","Log the 'bad rsv' message values to identify which bit the peer misuses"],"tags":["websocket","rsv-bits","compression","permessage-deflate"],"backgroundTag":"invalid-argument-value","analyzedSha":"afeacbf8c0f6f6a761c9d9daed8c813dd3b8ed7d","analyzedAt":"2026-09-09T14:39:47.546Z","contentChangedAt":"2026-09-09T14:39:47.546Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}