andrewt-8x8 opened a new issue, #25708: URL: https://github.com/apache/pulsar/issues/25708
### Search before reporting - [x] I searched in the [issues](https://github.com/apache/pulsar/issues) and found nothing similar. ### Read release policy - [x] I understand that [unsupported versions](https://pulsar.apache.org/contribute/release-policy/#supported-versions) don't get bug fixes. I will attempt to reproduce the issue on a supported version of Pulsar client and Pulsar broker. ### User environment Broker Version 4.0.7 Any broker OS Any broker Java version Any WebSocket client ### Issue Description ### Minimal reproduction steps Connect to the WebSocket reader endpoint with an invalid `messageId` query parameter. Two examples that both trigger the bug: 1. An improperly URL-encoded base64 message ID that includes a `+` which the server interprets as a space (e.g. `CJCj6QEQ+UQwAA==` becomes `CJCj6QEQ UQwAA==`). 2. An arbitrary non-base64 string: `?messageId=invalidMessageId` ### What did you expect to see? HTTP 400 Bad Request. ### What did you see instead? HTTP 500 Internal Server Error in both cases. **Case 1** — `IllegalArgumentException` from `Base64.getDecoder().decode()`: ``` WARN org.apache.pulsar.websocket.ReaderHandler - [REDACTED] Failed in creating reader on topic persistent://REDACTED/REDACTED/REDACTED java.lang.IllegalArgumentException: Illegal base64 character 20 at java.base/java.util.Base64$Decoder.decode0(Unknown Source) ~[?:?] at java.base/java.util.Base64$Decoder.decode(Unknown Source) ~[?:?] at java.base/java.util.Base64$Decoder.decode(Unknown Source) ~[?:?] at org.apache.pulsar.websocket.ReaderHandler.getMessageId(ReaderHandler.java:348) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.ReaderHandler.<init>(ReaderHandler.java:95) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.WebSocketReaderServlet.lambda$configure$0(WebSocketReaderServlet.java:44) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] ``` **Case 2** — `IOException` wrapping `IndexOutOfBoundsException` from `MessageIdImpl.fromByteArray()`: ``` WARN org.apache.pulsar.websocket.ReaderHandler - [REDACTED] Failed in creating reader on topic persistent://REDACTED/REDACTED/REDACTED java.io.IOException: java.lang.IndexOutOfBoundsException: readerIndex(5) + length(641882) exceeds writerIndex(12): UnpooledHeapByteBuf(ridx: 5, widx: 12, cap: 12/12) at org.apache.pulsar.client.impl.MessageIdImpl.fromByteArray(MessageIdImpl.java:93) ~[org.apache.pulsar-pulsar-client-original-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.ReaderHandler.getMessageId(ReaderHandler.java:348) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.ReaderHandler.<init>(ReaderHandler.java:95) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.WebSocketReaderServlet.lambda$configure$0(WebSocketReaderServlet.java:44) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(5) + length(641882) exceeds writerIndex(12): UnpooledHeapByteBuf(ridx: 5, widx: 12, cap: 12/12) at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1442) ~[io.netty-netty-buffer-4.1.127.Final.jar:4.1.127.Final] at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1428) ~[io.netty-netty-buffer-4.1.127.Final.jar:4.1.127.Final] at io.netty.buffer.AbstractByteBuf.skipBytes(AbstractByteBuf.java:971) ~[io.netty-netty-buffer-4.1.127.Final.jar:4.1.127.Final] at org.apache.pulsar.common.api.proto.LightProtoCodec.skipUnknownField(LightProtoCodec.java:264) ~[org.apache.pulsar-pulsar-common-4.0.7.jar:4.0.7] at org.apache.pulsar.common.api.proto.MessageIdData.parseFrom(MessageIdData.java:304) ~[org.apache.pulsar-pulsar-common-4.0.7.jar:4.0.7] at org.apache.pulsar.client.impl.MessageIdImpl.fromByteArray(MessageIdImpl.java:91) ~[org.apache.pulsar-pulsar-client-original-4.0.7.jar:4.0.7] ``` ### Details `ReaderHandler.getMessageId()` performs no validation on the `messageId` query parameter before passing it to `Base64.getDecoder().decode()` and `MessageIdImpl.fromByteArray()`. `ReaderHandler`'s constructor catches `Exception` during setup but hardcodes `HttpServletResponse.SC_INTERNAL_SERVER_ERROR` in the error response. `ConsumerHandler` and `ProducerHandler` both call `AbstractWebSocketHandler.getErrorCode(e)` instead, which maps `IllegalArgumentException` to `SC_BAD_REQUEST` (400). ### Error messages ```text **Case 1** — `IllegalArgumentException` from `Base64.getDecoder().decode()`: WARN org.apache.pulsar.websocket.ReaderHandler - [REDACTED] Failed in creating reader on topic persistent://REDACTED/REDACTED/REDACTED java.lang.IllegalArgumentException: Illegal base64 character 20 at java.base/java.util.Base64$Decoder.decode0(Unknown Source) ~[?:?] at java.base/java.util.Base64$Decoder.decode(Unknown Source) ~[?:?] at java.base/java.util.Base64$Decoder.decode(Unknown Source) ~[?:?] at org.apache.pulsar.websocket.ReaderHandler.getMessageId(ReaderHandler.java:348) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.ReaderHandler.<init>(ReaderHandler.java:95) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.WebSocketReaderServlet.lambda$configure$0(WebSocketReaderServlet.java:44) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] **Case 2** — `IOException` wrapping `IndexOutOfBoundsException` from `MessageIdImpl.fromByteArray()`: WARN org.apache.pulsar.websocket.ReaderHandler - [REDACTED] Failed in creating reader on topic persistent://REDACTED/REDACTED/REDACTED java.io.IOException: java.lang.IndexOutOfBoundsException: readerIndex(5) + length(641882) exceeds writerIndex(12): UnpooledHeapByteBuf(ridx: 5, widx: 12, cap: 12/12) at org.apache.pulsar.client.impl.MessageIdImpl.fromByteArray(MessageIdImpl.java:93) ~[org.apache.pulsar-pulsar-client-original-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.ReaderHandler.getMessageId(ReaderHandler.java:348) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.ReaderHandler.<init>(ReaderHandler.java:95) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] at org.apache.pulsar.websocket.WebSocketReaderServlet.lambda$configure$0(WebSocketReaderServlet.java:44) ~[org.apache.pulsar-pulsar-websocket-4.0.7.jar:4.0.7] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(5) + length(641882) exceeds writerIndex(12): UnpooledHeapByteBuf(ridx: 5, widx: 12, cap: 12/12) at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1442) ~[io.netty-netty-buffer-4.1.127.Final.jar:4.1.127.Final] at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1428) ~[io.netty-netty-buffer-4.1.127.Final.jar:4.1.127.Final] at io.netty.buffer.AbstractByteBuf.skipBytes(AbstractByteBuf.java:971) ~[io.netty-netty-buffer-4.1.127.Final.jar:4.1.127.Final] at org.apache.pulsar.common.api.proto.LightProtoCodec.skipUnknownField(LightProtoCodec.java:264) ~[org.apache.pulsar-pulsar-common-4.0.7.jar:4.0.7] at org.apache.pulsar.common.api.proto.MessageIdData.parseFrom(MessageIdData.java:304) ~[org.apache.pulsar-pulsar-common-4.0.7.jar:4.0.7] at org.apache.pulsar.client.impl.MessageIdImpl.fromByteArray(MessageIdImpl.java:91) ~[org.apache.pulsar-pulsar-client-original-4.0.7.jar:4.0.7] ``` ### Reproducing the issue Connect to the WebSocket reader endpoint with an invalid `messageId` query parameter. Two examples that both trigger the bug: 1. An improperly URL-encoded base64 message ID that includes a `+` which the server interprets as a space (e.g. `CJCj6QEQ+UQwAA==` becomes `CJCj6QEQ UQwAA==`). 2. An arbitrary non-base64 string: `?messageId=invalidMessageId` ### Additional information `ReaderHandler.getMessageId()` performs no validation on the `messageId` query parameter before passing it to `Base64.getDecoder().decode()` and `MessageIdImpl.fromByteArray()`. `ReaderHandler`'s constructor catches `Exception` during setup but hardcodes `HttpServletResponse.SC_INTERNAL_SERVER_ERROR` in the error response. `ConsumerHandler` and `ProducerHandler` both call `AbstractWebSocketHandler.getErrorCode(e)` instead, which maps `IllegalArgumentException` to `SC_BAD_REQUEST` (400). ### Are you willing to submit a PR? - [ ] I'm willing to submit a PR! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
