spring-boot: Allow custom ErrorReportValve to be used with Tomcat and provide whitelabel version
During a penetration test one finding was the information disclosure of using a Tomcat webserver.
If a request with an invalid URL (e.g. http://localhost:8080/[test ) is executed the configured custom error pages are not used.
Instead the embedded Tomcats ErrorReportValve
is used and presents a default Tomcat Error page.
It is possible to configure it to some extends using
server.error.whitelabel.enabled=false
server.error.include-stacktrace=never
But the default HTTP Status 400
page is always returned.
It is possible to create a custom ErrorReportValve
and set the properties like errorCode.400
to create a custom page, but this configuration is not possible with an application.properties
file.
(At least as far as I can see) See an example project at https://github.com/patst/tomcat-errorvalve
Maybe it would be a good idea to expose the properties for configuration.
The ErrorReportValve
is created at https://github.com/spring-projects/spring-boot/blob/767156167b4d1d91c8af0e5bff2d1be0d5149651/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.java#L295
What do you think?
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 1
- Comments: 24 (9 by maintainers)
I hit this issue with a request header that was too large.
Looks like I am able to get around the default configuration like this, without any changes to Spring. The key is the setErrorReportValveClass(), and the getOrder().
Then create that class aaa.bbb.ccc.configuration.CustomTomcatErrorValve
This valve can be configured however you’d like, BUT as discussed above, you don’t have too many options because the context hasn’t (may not have) been set in the Request yet, so you can’t redirect and setting setProperty(“errorCode.0”, … ) requires a File path. So here, I’m just returning the error text directly.
It’s also possible to do this, instead of a direct response…
but… I’m not sure that’s better. If the tomcat request is dying so early that we can’t do a normal redirect, or forward, than it’s probably not really safe to expect the /error page will work either. But if you have an external error page you could reference, that could be nicer.
I could see Spring following the above to provide an internal Spring ErrorValve that generates the disaster HTML response, and then taking it from a server.error.disaster-html type property. Or even allowing a FunctionalInterface customizer that generates text,
We’re probably not going to be able to customize the
ErrorReportValve
becausevalve.setProperty
requires a file and that won’t work with fat jars.We’d like to investigate a little more to find out why the
ErrorReportValve
is being used and theDispatcherServlet
isn’t being called at all.You should use
addContextCustomizers
rather thansetTomcatContextCustomizers
as the latter will replace any existing customizers.For anyone trying @sc-moonlight’s workaround (many thanks for this!), I had to add the following line to get it to work:
((StandardHost) parent).addValve(new CustomTomcatErrorValve());
With Jetty, a request with an illegal HTTP header produces the following response:
Undertow produces the following response:
If we can’t route into the app and its error pages, Undertow’s response seems like the best alternative as there’s nothing in it that could be used to identify the server that is producing the response.