Upgrading our application to Spring 6 with Spring Security 6.1.2 and Tomcat 10.1 resulted in the following UnsupportedOperationException:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'filterChain' threw exception with message: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:171)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
... 78 common frames omitted
Caused by: java.lang.UnsupportedOperationException: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener
at org.apache.catalina.core.StandardContext$NoPluggabilityServletContext.getServletRegistrations(StandardContext.java:6233)
at org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry.requestMatchers(AbstractRequestMatcherRegistry.java:197)
at org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry.requestMatchers(AbstractRequestMatcherRegistry.java:248)
at x.y.z.SecurityLocalConfiguration.lambda$filterChain$0(SecurityLocalConfiguration.java:42)
at org.springframework.security.config.annotation.web.builders.HttpSecurity.authorizeHttpRequests(HttpSecurity.java:1466)
at x.y.z.SecurityLocalConfiguration.filterChain(SecurityLocalConfiguration.java:41)
at x.y.z.SecurityLocalConfiguration$$SpringCGLIB$$0.CGLIB$filterChain$2(<generated>)
at x.y.z.SecurityLocalConfiguration$$SpringCGLIB$$2.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at x.y.z.SecurityLocalConfiguration$$SpringCGLIB$$0.filterChain(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139)
... 79 common frames omitted
The code that caused this is:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, Filter autoLoginFilter) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/alive").permitAll()
.anyRequest().authenticated()
)
.build();
}
Our current workaround is to not use requestMatchers with String arguments but to pass a AntPathRequestMatcher.
This ensures our application works again.
Working code:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, Filter autoLoginFilter) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(new AntPathRequestMatcher("/alive")).permitAll()
.anyRequest().authenticated()
)
.build();
}
The implementation of the requestMatchers method was altered in response to CVE https://spring.io/security/cve-2023-34035
PR and commit can be found in this issue: https://github.com/spring-projects/spring-security/issues/13551
The requestMatchers method has been changed to call servletContext.getServletRegistrations(); in commit
Tomcat does not seem to allow this and throws the UnsupportedOperationException.
This also matches the javadoc of the getServletRegistrations method
While searching for a solution I found this old issue https://github.com/spring-projects/spring-security/issues/4027 that had the same exception after a code change that also used servletContext.getServletRegistrations();.
This was reverted by this PR: https://github.com/spring-projects/spring-security/pull/4031
It seems that the mitigation for cve-2023-34035 might need a different solution to ensure it works on tomcat 10.1?
Comment From: stevegcc
I've run into the same issue and I've reverted to Spring Security 6.0.4 as per the recommendation here. This works for me.
I wasn't willing to go down the path of using AntPathRequestMatchers as it doesn't look like it allows defining multiple paths for a single HTTP method and I have a lot of configuration setup like the config below where there are several paths per method that have the same authority requirements.
.requestMatchers(
POST,
"/accounts",
"/auth/forgot-password",
"/webhooks/**"
).permitAll()
Comment From: jesudornenkrone
I ran into an similar issue, so i reverted back to spring-security 6.1.1 which ist not ideal, because of CVE-2023-34034.
Here my code, that causes the error mesage:
@Configuration @EnableWebSecurity public class AxWebSecurityConfig { @Bean @Order(1) public SecurityFilterChain filterChainTardis(HttpSecurity httpSecurityIn) throws Exception { ...
return httpSecurityIn.build();
}
@Bean
@Order(2)
public SecurityFilterChain filterChainSSO(HttpSecurity httpSecurityIn) throws Exception {
...
return httpSecurityIn.build();
}
@Bean
@Order(3)
public SecurityFilterChain filterChainUserNamePassword(HttpSecurity httpSecurityIn) throws Exception {
...
return httpSecurityIn.build();
}
}
Comment From: jesudornenkrone
Okay, I traced the problem a little. The Issue is that i use a WebApplicationInitializer adding a ContextLoaderListener. If I remove the ContextLoaderListener from the equation, it works (but I am not sure, if every part of the application is loaded).
However I thought I followed the example from javadoc of org.springframework.web.WebApplicationInitializer. So how can I do this compatible with Spring-Security 6.1.2+:
public class MyWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer { @Override protected void beforeSpringSecurityFilterChain(final ServletContext servletContextIn) { .... servletContextIn.addListener(new MyContextLoaderListener(applicationContext); } }
public class MyContextLoaderListener extends ContextLoaderListener {
public AxContextLoaderListener(AnnotationConfigWebApplicationContext applicationContext) {
super(applicationContext);
}
@Override
public void contextInitialized(final ServletContextEvent sce) {
super.contextInitialized(sce);
...
}
...
}
Comment From: JohnZ1385
any updates on this? I'm seeing similar issues on 5.8.9