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?