Describe the bug

When CSRF handling is enabled in a Spring Cloud Gateway Webflux setup it can eventually lead to cloud gateway sending corrupt requests to the downstream webserver.

When it finally gets corrupted request send to the downstream webserver do not contain a valid HTTP request method. It starts with part of the request.

The attempt to retrieve the CSRF token from the exchange's form data in org.springframework.security.web.server.csrf.ServerCsrfTokenRequestHandler eventually causes the corruption.

If you only use CSRF tokens in the request headers you can work around this problem by a slight modification of the request handler:

csrf.csrfTokenRequestHandler(new ServerCsrfTokenRequestAttributeHandler() {
    @Override
    public Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {
        return Mono.defer(() -> {
            String token = exchange.getRequest().getHeaders().getFirst(csrfToken.getHeaderName());
            if (token != null) {
                return Mono.just(token);
            }
            return Mono.empty();
        });
    }
});

Note that the request which get corrupted include GET requests.

This issue might be related to https://github.com/spring-projects/spring-security/issues/11687

To Reproduce

It is quite difficult to reproduce. I ran into this issue when trying out the Zed Attack Proxy against our software stack. It was the Spring4Shell injection which showed the problem. ZAP's Spring4Shell shows false positives, but it using it does reveal the problem with the request corruption.

I created an minimal example project and instructions on how to trigger the problem: https://github.com/elmuerte/spring-sec-csrf-cloud-gateway-bug

Expected behavior

The request send to the downstream webserver should be correct and not corrupted by the CSRF handling.

Sample

See this repo for an example application and reproduction steps: https://github.com/elmuerte/spring-sec-csrf-cloud-gateway-bug