If I send input filed like for GET /Users/{name} -- Name of User = "User1;" or "User2%" we can see the following response with full stack trace information. With this "//", "\", we are not seeing the full stack trace info in response. Based on my investigation I found that with for "%" and ";" has different workflows then other special chars like "//", "\" etc . It is going through StrictHttpFirewall.rejectedBlacklistedUrls() which is a private method of part of the Spring-Security-web framework. and eventually, it goes to the tomcat embed core - ErrorReportValue.report class wherein HTML tags, all stack traces are appended to it, which we are seeing in the response.
<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> The request was rejected because the URL contained a potentially malicious String "%25"</p><p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p><p><b>Exception</b></p><pre>org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String "%25"
org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlacklistedUrls(StrictHttpFirewall.java:325)
org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:293)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:194)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:113)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:130)
org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:66)
org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:105)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:123)
</pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p><hr class="line" /><h3>Apache Tomcat/9.0.30</h3></body></html>
I do not want to show full stack trace information to the user. Maybe we could extend StrictHttpFirewall to catch RequestRejectedException and throws a new exception with metadata from the request and a suppressed stack trace. But I do not want to make override or making a change in the spring framework. Can anyone help me if there is another way to hide the full stack trace from the response?
I am using "5.1.14.RELEASE" for spring version and tomcat 9.0.30