How to Mitigate the Unpublished Spring Framework RCE Vulnerability in JDK 9+ Environments

This article explains the newly disclosed Spring Framework remote code execution flaw affecting JDK 9+ Spring MVC/WebFlux applications deployed as WARs on Apache Tomcat, outlines the affected conditions, current patch status, and provides code‑level workarounds for safe remediation.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
How to Mitigate the Unpublished Spring Framework RCE Vulnerability in JDK 9+ Environments

1. Overview

Spring Framework confirmed an RCE vulnerability that had not yet been assigned a CVE. It was first reported to VMware on Tuesday night, investigated, fixed, tested, and scheduled for an emergency release on Thursday. The vulnerability was leaked online on Wednesday, after which Spring published a CVE.

2. About this RCE

The flaw affects Spring MVC and Spring WebFlux applications running on JDK 9+ when packaged as a WAR and deployed to Apache Tomcat. It does not affect embedded Tomcat in Spring Boot, though the vulnerability may be exploitable by other means.

3. Are you affected?

The report specifies the following requirements:

JDK 9 or higher

Apache Tomcat as the servlet container

Packaged as a WAR

However, the vulnerability’s nature is broader and other, unreported exploitation methods may exist.

4. Status

Spring Framework 5.3.18 and 5.2.20 have been released. Corresponding Spring Boot versions are in progress and expected within the next hour.

5. Fixes

Note: Spring Framework versions 5.3.18 and 5.2.20 address the issue and are available on Maven Central. If you can upgrade, no further workaround is needed.

The leaked report suggests the following configuration:

@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
public class BinderControllerAdvice {
    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
        dataBinder.setDisallowedFields(denylist);
    }
}

This usually works, but as a global fix it may leave gaps if controllers set their own bindings locally.

For a safer approach, the application can extend after all other initializations. In Spring Boot, declare a bean for Spring MVC or Spring WebFlux.

Example for Spring MVC (similar for WebFlux):

package car.app;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.InitBinderDataBinderFactory;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;

@SpringBootApplication
public class MyApp {

    public static void main(String[] args) {
        SpringApplication.run(CarApp.class, args);
    }

    @Bean
    public WebMvcRegistrations mvcRegistrations() {
        return new WebMvcRegistrations() {
            @Override
            public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
                return new ExtendedRequestMappingHandlerAdapter();
            }
        };
    }

    private static class ExtendedRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {

        @Override
        protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> methods) {
            return new ServletRequestDataBinderFactory(methods, getWebBindingInitializer()) {
                @Override
                protected ServletRequestDataBinder createBinderInstance(
                        Object target, String name, NativeWebRequest request) throws Exception {

                    ServletRequestDataBinder binder = super.createBinderInstance(target, name, request);
                    String[] fields = binder.getDisallowedFields();
                    List<String> fieldList = new ArrayList<>(fields != null ? Arrays.asList(fields) : Collections.emptyList());
                    fieldList.addAll(Arrays.asList("class.*", "Class.*", "*.class.*", "*.Class.*"));
                    binder.setDisallowedFields(fieldList.toArray(new String[] {}));
                    return binder;
                }
            };
        }
    }
}

For Spring MVC applications without Spring Boot, you can switch to the extended configuration using @EnableWebMvc and delegating to DelegatingWebMvcConfiguration, then override the createRequestMappingHandlerAdapter method.

References

[1] Advanced configuration: https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-config-advanced-java

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSecuritypatchTomcatRCESpring MVCSpring Framework
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.