How HTTP Works

Method · safe · idempotent

> TRACE /hello HTTP/1.1>  Host: example.com>  Max-Forwards: 2

HTTP TRACE Method: What It Does and Why to Disable It

HTTP TRACE echoes the request back for diagnostics. Cross-Site Tracing history, why scanners flag "TRACE enabled", and how to disable it in Apache and nginx.

Reviewed 3 min readintermediate4 sourcesMarkdown
Safe
Yes
Idempotent
Yes
Cacheable
No
Request body
Not allowed
Response body
Yes (message/http echo)
Spec
RFC 9110 §9.3.8
On this page

TL;DR: TRACE makes a server echo your request back as message/http, a diagnostic from the 1990s. Browsers forbid it in fetch and XMLHttpRequest, but scanners still flag servers that answer it, so turn it off: TraceEnable off in Apache, and make sure nginx or your backend returns 405.

What it does

A TRACE request carries no body. The server (or the last proxy, when Max-Forwards runs down to 0) replies 200 and puts the request it received in the body. RFC 9110 section 9.3.8 specifies it:

TRACE /hello HTTP/1.1
Host: example.com
Max-Forwards: 2
HTTP/1.1 200 OK
Content-Type: message/http

TRACE /hello HTTP/1.1
Host: example.com
Max-Forwards: 1
Via: 1.1 edge-proxy

The point was to see how intermediaries changed the request: a proxy that added a Via header or decremented Max-Forwards shows up in the echo. The RFC says a client must not send content or sensitive fields such as cookies or credentials in a TRACE request, and that a server should not reflect fields that could hold sensitive data. Nobody uses it for diagnostics now; curl -v, Via and proxy logs do the job.

Cross-Site Tracing and why it is still flagged

In 2003 Jeremiah Grossman published a white paper on Cross-Site Tracing (XST). The trick: an XSS payload sends a TRACE request to the victim site. The browser attaches its cookies (and any cached HTTP credentials) automatically, the server echoes them back in the body, and the script reads the body. That defeated HttpOnly, which only hides cookies from document.cookie, not from an echoed response.

Browsers closed the browser-side path by refusing to send TRACE from script. The Fetch Standard lists CONNECT, TRACE and TRACK as forbidden methods, so fetch('/', { method: 'TRACE' }) rejects with a TypeError before anything goes on the network. XST as originally described is therefore not practical against current browsers, and the finding is usually rated low severity.

Scanners (Nessus, Qualys, OWASP ZAP, PCI ASV tooling) still report “HTTP TRACE method enabled” because the check is cheap and the remedy is trivial. Treat it as hygiene: it removes a finding and an echo endpoint that can leak headers added by proxies or gateways, such as internal forwarding or authentication headers.

Check whether it is enabled

curl -i -X TRACE https://example.com/

A server that supports it returns 200 OK with Content-Type: message/http. A hardened one returns 405, 403 or 501. Test the public hostname, not only the origin, because a CDN or load balancer in front can answer differently from the server behind it.

Disable it

Apache has a dedicated directive, and it defaults to on:

TraceEnable off

With that set, Apache answers TRACE with 405 Method Not Allowed (checked on httpd 2.4). The directive is valid in server config and virtual host context, not .htaccess. TraceEnable extended goes the other way and allows a request body, for conformance testing.

nginx has no TRACE feature to switch off. Serving its own content, stock nginx replies 405 Not Allowed to TRACE (tested on the official nginx:alpine image). When you proxy_pass, nginx forwards the method upstream, so a backend that echoes TRACE is reachable through it. Block unwanted methods at the edge:

server {
    # Allow only the methods this site uses
    if ($request_method !~ ^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS)$) {
        return 405;
    }
}

Tomcat disables it by default: the allowTrace attribute on <Connector> defaults to false.

TRACE is safe and idempotent in RFC 9110 terms but not cacheable. If your scan also lists unexpected OPTIONS or PUT, see OPTIONS; a rejected method comes back as 405 or 501.

Frequently asked questions

What does the HTTP TRACE method do?

TRACE asks the server to echo the request it received back in the response body as message/http. Combined with Max-Forwards it was meant for seeing how proxies along the path rewrote a request, a loop-back diagnostic.

Why does my vulnerability scanner report "HTTP TRACE method enabled"?

The scanner sent a TRACE request and got a 200 with the request echoed. That is the precondition for Cross-Site Tracing, so scanners and PCI-style audits flag it even though modern browsers cannot be made to send TRACE from script. The finding clears when the server answers 405, 501 or 403 instead.

What was Cross-Site Tracing (XST)?

A 2003 technique in which injected JavaScript sent a TRACE request through XMLHttpRequest or a plugin, so the echoed response exposed headers that script was not supposed to read, notably HttpOnly cookies and Authorization. Browsers responded by forbidding TRACE in script, which closed the browser-side route.

How do I disable TRACE in Apache?

Add TraceEnable off to the server config or a virtual host. Apache then answers TRACE with 405 Method Not Allowed. The directive defaults to on, so the method is available unless you turn it off.

Does nginx support TRACE?

Not as an echo. nginx serving its own content answers TRACE with 405 Not Allowed, which we confirmed on the official nginx:alpine container. When nginx proxies with proxy_pass it forwards the method upstream, so block it in nginx or make sure the backend rejects it.

Sources

  1. MDN Web Docs: TRACEdeveloper.mozilla.org
  2. RFC 9110 section 9.3.8: TRACErfc-editor.org
  3. Apache HTTP Server: TraceEnablehttpd.apache.org
  4. Fetch Standard: forbidden methodfetch.spec.whatwg.org

Keep going

Browse /search