From ec448b51c05cc0f6803c1fff6f19ab7924577417 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Sat, 9 Nov 2024 16:46:17 -0500 Subject: [PATCH] Clarify SECURITY-3315 error code on client side (#9930) --- core/src/main/java/hudson/cli/CLIAction.java | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/cli/CLIAction.java b/core/src/main/java/hudson/cli/CLIAction.java index a2fc5f590197..a2e756267178 100644 --- a/core/src/main/java/hudson/cli/CLIAction.java +++ b/core/src/main/java/hudson/cli/CLIAction.java @@ -118,12 +118,26 @@ public boolean isWebSocketSupported() { return WebSockets.isSupported(); } + /** + * Unlike {@link HttpResponses#errorWithoutStack} this sends the message in a header rather than the body. + * (Currently the WebSocket CLI is unable to process the body in an error message.) + */ + private static HttpResponse statusWithExplanation(int code, String errorMessage) { + return new HttpResponse() { + @Override + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) { + rsp.setStatus(code); + rsp.setHeader("X-CLI-Error", errorMessage); + } + }; + } + /** * WebSocket endpoint. */ public HttpResponse doWs(StaplerRequest2 req) { if (!WebSockets.isSupported()) { - return HttpResponses.notFound(); + return statusWithExplanation(HttpServletResponse.SC_NOT_FOUND, "WebSocket is not supported in this servlet container (try the built-in Jetty instead)"); } if (ALLOW_WEBSOCKET == null) { final String actualOrigin = req.getHeader("Origin"); @@ -141,10 +155,10 @@ public HttpResponse doWs(StaplerRequest2 req) { if (actualOrigin == null || !actualOrigin.equals(expectedOrigin)) { LOGGER.log(Level.FINE, () -> "Rejecting origin: " + actualOrigin + "; expected was from request: " + expectedOrigin); - return HttpResponses.forbidden(); + return statusWithExplanation(HttpServletResponse.SC_FORBIDDEN, "Unexpected request origin (check your reverse proxy settings)"); } } else if (!ALLOW_WEBSOCKET) { - return HttpResponses.forbidden(); + return statusWithExplanation(HttpServletResponse.SC_FORBIDDEN, "WebSocket support for CLI disabled for this controller"); } Authentication authentication = Jenkins.getAuthentication2(); return WebSockets.upgrade(new WebSocketSession() {