Spring Boot 3.3.5 includes spring-security-web-6.3.4.jar. The newly introduced class org.springframework.security.web.server.firewall.StrictServerWebExchangeFirewall$StrictFirewallServerWebExchange$StrictFirewallHttpRequest$StrictFirewallHttpHeaders isn't supported by org.springframework.http.HttpHeaders.writableHttpHeaders(). As a result the following exception is being thrown if the ServerWebExchange webflux request is being mutated and an http header is modified or added:
java.lang.UnsupportedOperationException: null
at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:130) ~[spring-web-6.1.14.jar:6.1.14]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
*__checkpoint ⇢ org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers$MutatorFilter [DefaultWebFilterChain]
*__checkpoint ⇢ HTTP GET "/api/mycontroller" [ExceptionHandlingWebHandler]
Original Stack Trace:
at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:130) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:39) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.http.HttpHeaders.put(HttpHeaders.java:1779) ~[spring-web-6.1.14.jar:6.1.14]
at org.springframework.http.server.reactive.DefaultServerHttpRequestBuilder.header(DefaultServerHttpRequestBuilder.java:110) ~[spring-web-6.1.14.jar:6.1.14]
at app.SetHttpHeaderWebFilter.filter(SetHttpHeaderWebFilter.java:21) ~[main/:na]
at org.springframework.web.server.handler.DefaultWebFilterChain.invokeFilter(DefaultWebFilterChain.java:114) ~[spring-web-6.1.14.jar:6.1.14]
I set up a small github project github StrictFirewallHttpHeaders. Simply run "gradlew clean test" to reproduce the error.
Comment From: evgeniycheban
Hi, @jzheaux, can I work on this?
Comment From: ducvo-kms
@sestrel, @evgeniycheban . We have the same issue. I found issue reported and fixed in https://github.com/spring-projects/spring-framework/issues/33789 in commit https://github.com/spring-projects/spring-framework/commit/a06bbccf9ecccd41f1099e0462005478cc84974b
Comment From: jzheaux
Sure, @evgeniycheban. You might begin by writing a failing test and seeing if it passes once you update to the latest Spring Framework snapshot.
Comment From: rwinch
Closing as duplicate of https://github.com/spring-projects/spring-security/issues/15989 which is superseded by https://github.com/spring-projects/spring-framework/issues/33789
Comment From: keerthimunikoti1807
I tried to upgrade spring-security-web to 6.3.4 to fix CVE-2024-38821 and faced this issue.
@rwinch I use putHeaders function where it replaces original headers with new headers. Could you please tell me how I can modify this to work?
private void putHeaders(HttpHeaders origHeaders, HttpHeaders newHeaders) { newHeaders.forEach((key, value) -> origHeaders.put(key, value)); }
ServerHttpRequest request = exchange.getRequest().mutate().headers(headers -> putHeaders(headers, newHeaders)).build();
Comment From: rwinch
@keerthimunikoti1807 Did you see the workaround in the the issue that I indicated that this duplicates?