spring-projects / spring-projects/spring-security
Spring Security 6.1.2 String requestMatchers error UnsupportedOperationException
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
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?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at AbstractRequestMatcherRegistry.requestMatchers, where the issue reports a call to servletContext.getServletRegistrations(), and compare that change with the linked CVE-2023-34035 commit and the earlier issue 4027/PR 4031. Reproduce the UnsupportedOperationException on Tomcat 10.1 using the String matcher example. Done means the mitigation remains effective without breaking this configuration or requiring the AntPathRequestMatcher workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100