From 4e1763bb8f99ab437b7da6dbd19556daa1b9f20e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 09:15:50 +0000 Subject: [PATCH 1/2] Fix arbitrary Origin reflection in CorsRequestHandler - Set `Access-Control-Allow-Origin` to `*` instead of echoing request header - Update `CorsRequestHandlerTest` to assert wildcard origin Co-authored-by: tomdesair <14034630+tomdesair@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ .../java/me/desair/tus/server/cors/CorsRequestHandler.java | 2 +- .../me/desair/tus/server/cors/CorsRequestHandlerTest.java | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 73c52c95..c2c07f0f 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -19,3 +19,7 @@ **Vulnerability:** A CRLF injection vulnerability was identified where unvalidated inputs could be reflected directly into HTTP response headers, leading to HTTP response splitting. **Learning:** Instead of sanitizing individual headers independently, the overarching wrapper that interacts with the HTTP response output should inherently validate and sanitize the input to prevent injection across all headers. **Prevention:** `TusServletResponse.java` was modified to include a `sanitizeHeaderValue` method, replacing any instances of `\r` and `\n` characters before interacting with the core `HttpServletResponse`, ensuring consistent CRLF prevention application-wide. +## 2026-09-08 - Fix Arbitrary Origin Reflection in CORS Configuration +**Vulnerability:** The `CorsRequestHandler.java` implementation blindly read the `Origin` header from incoming HTTP requests and reflected its exact value back in the `Access-Control-Allow-Origin` response header. +**Learning:** Blindly mirroring the request's origin bypasses the intended security of CORS restrictions and can lead to arbitrary cross-origin data exposure, effectively negating the same-origin policy enforcement by browsers. Moreover, doing so without `Vary: Origin` could lead to cache poisoning in intermediate CDNs. +**Prevention:** Hardcode public API endpoint CORS rules to return the explicitly permissive `*` (wildcard) instead of reflecting the user's string input. diff --git a/src/main/java/me/desair/tus/server/cors/CorsRequestHandler.java b/src/main/java/me/desair/tus/server/cors/CorsRequestHandler.java index 5bf72034..a0af1e2a 100644 --- a/src/main/java/me/desair/tus/server/cors/CorsRequestHandler.java +++ b/src/main/java/me/desair/tus/server/cors/CorsRequestHandler.java @@ -24,7 +24,7 @@ public void process( String origin = servletRequest.getHeader("Origin"); if (StringUtils.isNotBlank(origin)) { - servletResponse.setHeader("Access-Control-Allow-Origin", origin); + servletResponse.setHeader("Access-Control-Allow-Origin", "*"); servletResponse.setHeader( "Access-Control-Expose-Headers", "Upload-Offset, Upload-Length, Upload-Metadata, Upload-Expires, Upload-Concat, " diff --git a/src/test/java/me/desair/tus/server/cors/CorsRequestHandlerTest.java b/src/test/java/me/desair/tus/server/cors/CorsRequestHandlerTest.java index a26d114a..25eadfc7 100644 --- a/src/test/java/me/desair/tus/server/cors/CorsRequestHandlerTest.java +++ b/src/test/java/me/desair/tus/server/cors/CorsRequestHandlerTest.java @@ -53,7 +53,7 @@ public void processWithOrigin() throws Exception { handler.process(HttpMethod.GET, req, resp, null, null); - assertThat(mockResp.getHeader("Access-Control-Allow-Origin"), is("https://example.com")); + assertThat(mockResp.getHeader("Access-Control-Allow-Origin"), is("*")); assertThat( mockResp.getHeader("Access-Control-Expose-Headers"), is( @@ -70,7 +70,7 @@ public void processPreflight() throws Exception { handler.process(HttpMethod.OPTIONS, req, resp, null, null); - assertThat(mockResp.getHeader("Access-Control-Allow-Origin"), is("https://example.com")); + assertThat(mockResp.getHeader("Access-Control-Allow-Origin"), is("*")); assertThat( mockResp.getHeader("Access-Control-Allow-Methods"), is("POST, GET, HEAD, PATCH, DELETE, OPTIONS")); From 4e20a199334c9b7c714b16b01e69aedbf96a277c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 09:29:55 +0000 Subject: [PATCH 2/2] Fix arbitrary Origin reflection in CorsRequestHandler - Set `Access-Control-Allow-Origin` to `*` instead of echoing request header - Update `CorsRequestHandlerTest` and `AbstractITTusFileUploadService` to assert wildcard origin Co-authored-by: tomdesair <14034630+tomdesair@users.noreply.github.com> --- .../me/desair/tus/server/AbstractITTusFileUploadService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/me/desair/tus/server/AbstractITTusFileUploadService.java b/src/test/java/me/desair/tus/server/AbstractITTusFileUploadService.java index b51ec433..df5f5c87 100644 --- a/src/test/java/me/desair/tus/server/AbstractITTusFileUploadService.java +++ b/src/test/java/me/desair/tus/server/AbstractITTusFileUploadService.java @@ -1843,7 +1843,7 @@ public void testCorsHeaders() throws Exception { servletRequest.addHeader(HttpHeader.UPLOAD_LENGTH, 100L); tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY); - assertResponseHeader("Access-Control-Allow-Origin", "https://example.com"); + assertResponseHeader("Access-Control-Allow-Origin", "*"); assertResponseHeaderNotBlank("Access-Control-Expose-Headers"); } @@ -1856,7 +1856,7 @@ public void testCorsPreflight() throws Exception { servletRequest.addHeader("Access-Control-Request-Method", "PATCH"); tusFileUploadService.process(servletRequest, servletResponse, OWNER_KEY); - assertResponseHeader("Access-Control-Allow-Origin", "https://example.com"); + assertResponseHeader("Access-Control-Allow-Origin", "*"); assertResponseHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, PATCH, DELETE, OPTIONS"); assertResponseHeaderNotBlank("Access-Control-Allow-Headers"); assertResponseHeader("Access-Control-Max-Age", "86400");