diff --git a/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java index 73ef4679b4d..453cd23d9e8 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java @@ -83,8 +83,15 @@ public class DefaultCorsProcessor implements CorsProcessor { response.addHeader(HttpHeaders.VARY, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS); } - if (!CorsUtils.isCorsRequest(request)) { - return true; + try { + if (!CorsUtils.isCorsRequest(request)) { + return true; + } + } + catch (IllegalArgumentException ex) { + logger.debug("Reject: origin is malformed"); + rejectRequest(new ServletServerHttpResponse(response)); + return false; } if (response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) != null) { diff --git a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java index d15dcd122fe..7a4782be20f 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java +++ b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java @@ -83,8 +83,15 @@ public class DefaultCorsProcessor implements CorsProcessor { } } - if (!CorsUtils.isCorsRequest(request)) { - return true; + try { + if (!CorsUtils.isCorsRequest(request)) { + return true; + } + } + catch (IllegalArgumentException ex) { + logger.debug("Reject: origin is malformed"); + rejectRequest(response); + return false; } if (responseHeaders.getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) != null) { diff --git a/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java b/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java index 301154fe015..ad5964f5374 100644 --- a/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java +++ b/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java @@ -184,6 +184,20 @@ class DefaultCorsProcessorTests { assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue(); } + @Test //gh-33682 + public void actualRequestMalformedOriginRejected() throws Exception { + this.request.setMethod(HttpMethod.GET.name()); + this.request.addHeader(HttpHeaders.ORIGIN, "http://*@:;"); + this.conf.addAllowedOrigin("https://domain2.com"); + + boolean result = this.processor.processRequest(this.conf, this.request, this.response); + assertThat(result).isFalse(); + assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isFalse(); + assertThat(this.response.getHeaders(HttpHeaders.VARY)).contains(HttpHeaders.ORIGIN, + HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS); + assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN); + } + @Test void actualRequestExposedHeaders() throws Exception { this.request.setMethod(HttpMethod.GET.name()); diff --git a/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java b/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java index fcb805129d9..df86b40e8bf 100644 --- a/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java +++ b/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java @@ -190,6 +190,21 @@ class DefaultCorsProcessorTests { assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue(); } + @Test // gh-33682 + public void actualRequestMalformedOriginRejected() { + ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest + .method(HttpMethod.GET, "http://localhost/test.html") + .header(HttpHeaders.ORIGIN, "http://*@:;")); + + this.conf.addAllowedOrigin("https://domain2.com"); + boolean result = this.processor.process(this.conf, exchange); + ServerHttpResponse response = exchange.getResponse(); + + assertThat(result).isFalse(); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); + assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isFalse(); + } + @Test void actualRequestExposedHeaders() { ServerWebExchange exchange = actualRequest();