Skip to content

Commit 8da31e1

Browse files
committed
Reject CORS request with 403 if Origin header is malformed
When assessing if a request is a CORS request, both mvc and reactive `DefaultCorsProcessor` now catch `IllegalArgumentException` and turn this into a 403 rejection rather than letting the exception propagate into a 500 response. Closes gh-33688
1 parent f991c19 commit 8da31e1

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

Diff for: spring-web/src/main/java/org/springframework/web/cors/DefaultCorsProcessor.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,15 @@ public boolean processRequest(@Nullable CorsConfiguration config, HttpServletReq
8383
response.addHeader(HttpHeaders.VARY, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
8484
}
8585

86-
if (!CorsUtils.isCorsRequest(request)) {
87-
return true;
86+
try {
87+
if (!CorsUtils.isCorsRequest(request)) {
88+
return true;
89+
}
90+
}
91+
catch (IllegalArgumentException ex) {
92+
logger.debug("Reject: origin is malformed");
93+
rejectRequest(new ServletServerHttpResponse(response));
94+
return false;
8895
}
8996

9097
if (response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) != null) {

Diff for: spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,15 @@ public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exc
8383
}
8484
}
8585

86-
if (!CorsUtils.isCorsRequest(request)) {
87-
return true;
86+
try {
87+
if (!CorsUtils.isCorsRequest(request)) {
88+
return true;
89+
}
90+
}
91+
catch (IllegalArgumentException ex) {
92+
logger.debug("Reject: origin is malformed");
93+
rejectRequest(response);
94+
return false;
8895
}
8996

9097
if (responseHeaders.getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) != null) {

Diff for: spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java

+14
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,20 @@ public void actualRequestTrailingSlashOriginMatch() throws Exception {
184184
assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
185185
}
186186

187+
@Test //gh-33682
188+
public void actualRequestMalformedOriginRejected() throws Exception {
189+
this.request.setMethod(HttpMethod.GET.name());
190+
this.request.addHeader(HttpHeaders.ORIGIN, "http://*@:;");
191+
this.conf.addAllowedOrigin("https://domain2.com");
192+
193+
boolean result = this.processor.processRequest(this.conf, this.request, this.response);
194+
assertThat(result).isFalse();
195+
assertThat(this.response.containsHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).isFalse();
196+
assertThat(this.response.getHeaders(HttpHeaders.VARY)).contains(HttpHeaders.ORIGIN,
197+
HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
198+
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_FORBIDDEN);
199+
}
200+
187201
@Test
188202
void actualRequestExposedHeaders() throws Exception {
189203
this.request.setMethod(HttpMethod.GET.name());

Diff for: spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java

+15
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,21 @@ public void actualRequestTrailingSlashOriginMatch() {
190190
assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isTrue();
191191
}
192192

193+
@Test // gh-33682
194+
public void actualRequestMalformedOriginRejected() {
195+
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest
196+
.method(HttpMethod.GET, "http://localhost/test.html")
197+
.header(HttpHeaders.ORIGIN, "http://*@:;"));
198+
199+
this.conf.addAllowedOrigin("https://domain2.com");
200+
boolean result = this.processor.process(this.conf, exchange);
201+
ServerHttpResponse response = exchange.getResponse();
202+
203+
assertThat(result).isFalse();
204+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
205+
assertThat(response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN)).isFalse();
206+
}
207+
193208
@Test
194209
void actualRequestExposedHeaders() {
195210
ServerWebExchange exchange = actualRequest();

0 commit comments

Comments
 (0)