dotvitals

The response sends obsolete headers, one of them harmful

LowConfirmedQuick winhttp.headers.deprecated-header-present

What this check looks for

Some of these headers do nothing at all now. One of them switches on a browser feature that was removed because it could itself be used to attack the page.

Why it matters

Dead headers are worse than clutter: X-XSS-Protection reads like a protection you have, so it gets ticked off a checklist while providing nothing, and the browsers that did honour it had bugs that let it be turned against the page.

When the check passes, your report says: “Every header sent is one browsers still act on”.

What it costs your score

When this check fails it removes 3 points from your HTTP score, before the status, confidence and repeat multipliers are applied. HTTP carries a weight of 7 in the overall score.

It shares the http.hygiene family ceiling of 10 points: however many findings that family produces, together they cannot remove more than that from HTTP. One underlying problem showing up in several places is still one problem.

Severity
low
Default confidence
confirmed
Status when triggered
warn
Deduction
3 points
Family cap
http.hygiene · 10
Category
HTTP
Module
Http headers
Fix owned by
user
In the ruleset since
2026.09

How the whole score is calculated

How to fix it

Remove the obsolete headers and rely on the mechanisms that replaced them.

They provide nothing, and X-XSS-Protection's filter was itself an attack surface on the browsers that had it.

  1. Remove X-XSS-Protection entirely. If a compliance checklist demands the header, send X-XSS-Protection: 0 instead — that value disables the removed filter rather than requesting it, and this scanner does not report it.

  2. Deploy a Content Security Policy; that is the actual replacement for what the auditor pretended to do.

  3. Remove X-UA-Compatible and P3P — nothing current reads either.

  4. Replace Pragma: no-cache and Expires: 0 with an explicit Cache-Control: no-store for sensitive responses, no-cache for ones that must be revalidated.

  5. Remove them at the origin, not only at a proxy — a proxy that is bypassed serves them again.

How to confirm it worked

  • curl -sSI https://‹host›/ | grep -iE '^(x-xss-protection|x-ua-compatible|p3p|pragma|expires):' — expect nothing

The configuration to publish
Cache-Control: no-store
Content-Security-Policy: default-src 'self'

A named slot like ‹domain› — and the braces left in the configuration below — is filled in with your own values when this rule appears on a report.

Remediation by platform

nginx
# Requires the headers-more module (ngx_headers_more):
more_clear_headers 'X-XSS-Protection' 'X-UA-Compatible' 'P3P' 'Pragma';

# For a header added by a proxied upstream, stock nginx can do this instead:
# proxy_hide_header X-XSS-Protection;
Apache
<IfModule mod_headers.c>
	Header always unset X-XSS-Protection
	Header always unset X-UA-Compatible
	Header always unset P3P
	Header always unset Pragma
</IfModule>
Caddy
header {
	-X-XSS-Protection
	-X-UA-Compatible
	-P3P
	-Pragma
}
Cloudflare
Rules → Overview → Create rule → Response Header Transform Rule → Remove (path as at 2026-09).
  • Stock nginx cannot remove an arbitrary response header: add_header only adds, and proxy_hide_header works only for a header arriving from a proxied upstream. If neither applies, stop the application emitting it instead — which is the better fix in any case.

  • Shown because the response identified Apache. Put it in the virtual host or server configuration rather than .htaccess: .htaccess is re-read on every request, is often disabled by AllowOverride None, and runs too late to influence a response the virtual host generates itself. always matters here: without it the rule skips error responses, which are frequently the ones that leak the most.

  • This applies only to responses that reach visitors through Cloudflare. An origin that is reachable directly — by IP, or through a DNS record that is not proxied — still serves the response measured here unchanged. Setting it at the origin as well covers both paths.

Technical detail

Obsolete headers on the response from ‹origin›: ‹headers›. ‹detail›

What each one is:

  • **X-XSS-Protection: 1 / 1; mode=block** — the header that enables the legacy XSS auditor. Every major browser removed that filter: Edge dropped it in 2018, Chrome removed the auditor in version 78, and Firefox never implemented it. It was removed because it was a vulnerability in its own right — the filter could be steered into suppressing legitimate script to expose content it was protecting, and mode=block's abort behaviour was demonstrated as a cross-site leak channel. A real Content Security Policy is the replacement. **Note what this rule does not report:** X-XSS-Protection: 0 is *not* flagged, because that value explicitly disables the filter and is what OWASP recommends for the browsers that still have one. Removing the header entirely is equally fine today.
  • **X-UA-Compatible** — instructed Internet Explorer which rendering engine to emulate. IE has been out of support since June 2022 and the header is ignored by everything current.
  • **P3P** — a compact privacy policy for a W3C specification that was abandoned; only old IE ever consumed it, usually as a workaround to make third-party cookies work in frames.
  • **Pragma: no-cache** used as a cache directive — RFC 9111 §5.4 deprecates it outright and describes it as a *request* header. Alongside a Cache-Control it is inert; without one it is not a reliable instruction to anything.
  • **Expires: 0** used as a cache directive — an invalid date, which a cache treats as already expired. It happens to produce roughly the intended effect, which is why it survives, but it is a malformed value standing in for Cache-Control: no-store or no-cache.

None of these is urgent; all of them are one line to remove. Detected server: ‹detected server›.

Standards and references

Test this on your domain

Run the check that produces this finding, on its own, against any domain.

Open the http headers checkerBuild the fix

Other http headers checks