Skip to content

Option to disable TRACE completely #33623

@ieu

Description

@ieu

Tomcat by default disables TRACE request. Each TRACE reqeust retrives response like below:

HTTP/1.1 405
Allow: HEAD, GET, OPTIONS
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 735
Date: Thu, 22 Dec 2022 22:22:22 GMT

<!doctype html><html lang="en"><head><title>HTTP Status 405 – Method Not Allowed</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 405 – Method Not Allowed</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> TRACE method is not allowed</p><p><b>Description</b> The method received in the request-line is known by the origin server but not supported by the target resource.</p><hr class="line" /><h3>Apache Tomcat/10.0.27</h3></body></html>

Spring Boot follows the similar behaviour by responding 405 (Method Not Allowed). However, although response status code is set to 405, Spring Boot still outputs request headers in the body:

HTTP/1.1 405
Allow: HEAD, DELETE, POST, GET, OPTIONS, PUT
Content-Type: message/http
Content-Length: 273
Date: Thu, 22 Dec 2022 22:22:22 GMT

TRACE /error HTTP/1.1
host: localhost:8080
user-agent: curl/7.87.0
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.5

IMO it is wrong behavior. If it's not, then we need an option to disable/forbid TRACE completely.


Below is my thoughts on this issue.

By default, allowTrace attribute of Tomcat connector is set as false. This causes TRACE request forwarded to error page. In vanilla Spring Boot application, there is a BasicErrorController, by which the TRACE request is handled. We know that DispatcherServlet accepts and handles all requests, so if we take a look into implementation details of doTrace (Inherited from FrameworkServlet), we can easily figure it out why request headers are printed.

@Override
protected void doTrace(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

	if (this.dispatchTraceRequest) {
		processRequest(request, response);
		if ("message/http".equals(response.getContentType())) {
			// Proper TRACE response coming from a handler - we're done.
			return;
		}
	}
	super.doTrace(request, response);
}

By default, spring.mvc.dispatch-trace-request is set to false, therefore this.processRequest is bypassed and super.doTrace is called. In this context, HttpServlet.doTrace is called, by which request headers are printed.

What problem there is here is that FrameworkServlet.doTrace enforces corresponding handler to construct response in content type of message/http, but BasicErrorController does not handle TRACE request specifically.

Currently I find two ways to disable TRACE request completely.

One workaround is to disable ErrorMvcAutoConfiguration. When ErrorMvcAutoConfiguration is execluded on startup, Spring Boot will respond like below:

HTTP/1.1 405
Allow: HEAD, DELETE, POST, GET, OPTIONS, PUT
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 449
Date: Thu, 22 Dec 2022 22:22:22 GMT

<!doctype html><html lang="en"><head><title>HTTP Status 405 – Method Not Allowed</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 405 – Method Not Allowed</h1></body></html>

The other workaround is to enable spring.mvc.dispatch-trace-request and implements my own ErrorController which handles requests case by case.

However, neither of them is concise and good enough. The former cuts off global error handling at the same time, and the latter is also restricted to construct message/http compatible response, and may expose unexpected TRACE endpoints.

Furthermore to say, I think we need a mechanism to whitelist error handler and avoid it being handled by FrameworkServlet.doTrace, or least add an option to allow us to bypass message/http requirement for TRACE request, giving us maximum freedom to customize TRACE response.

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: external-projectFor an external project and not something we can fixstatus: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions