Start here
Before You Fix It: What This Check Means
Security headers are browser-level guardrails that reduce exploit surface before app code executes. In plain terms, this checks whether your site sends the main browser security headers and whether the critical ones are set to sensible values, not just present. Scavo looks at two groups of response headers.
Why this matters in practice: weak settings here can increase breach risk and incident blast radius before teams notice.
How to use this result: treat this as directional evidence, not final truth. A crawl snapshot cannot prove every route, subdomain, or transient edge rule is consistently configured. First, confirm the issue in live output: inspect live response headers and certificate state on the exact production host Then ship one controlled change: Capture the final production headers from the real route and environment Scavo tested. Finally, re-scan the same URL to confirm the result improves.
TL;DR: This check reviews the browser-facing headers that help stop common web attacks before your application code even gets involved. It does not just ask “is the header there?” It also checks whether key headers are set to values that actually make sense.
That distinction matters. A site can technically send X-Content-Type-Options, X-Frame-Options, or Referrer-Policy and still be too weak, empty, or obsolete to deliver the protection people assume is in place. So this check now treats missing, invalid, and clearly weak critical values as different kinds of problems instead of treating every non-empty header as a pass.
What Scavo checks (plain English)
Scavo looks at two groups of response headers.
Critical baseline headers in this check:
X-Frame-OptionsX-Content-Type-OptionsPermissions-PolicyReferrer-Policy
Recommended hardening headers tracked here:
Strict-Transport-SecurityContent-Security-PolicyCross-Origin-Opener-PolicyCross-Origin-Embedder-PolicyCross-Origin-Resource-Policy
Scavo now checks more than presence for the critical baseline:
X-Frame-Optionsshould use a valid protective value such asDENYorSAMEORIGINX-Content-Type-Optionsonly protects browsers when set tonosniffReferrer-Policyshould use a recognized policy, and obviously weak settings are downgradedPermissions-Policyshould not be blank if present
How Scavo scores this check:
- Pass: there are no critical header issues; some recommended headers may still be missing
- Warning: exactly one critical issue was found (missing, invalid, or weak)
- Fail: two or more critical issues were found
- Pass with note: critical headers are sound but one or more recommended hardening headers are still missing
How Scavo scores this check
Scavo assigns one result state for this check on the tested page:
- Pass: baseline signals for this check were found.
- Warning: partial coverage or risk signals were found and should be reviewed.
- Fail: required signals were missing or risky behavior was confirmed.
- Info: Scavo could not gather enough reliable evidence on this run to score pass/fail confidently.
In your scan report, this appears under What failed / What needs attention / What is working for security_headers, followed by Recommended next steps and Technical evidence (for developers) when needed.
- Scan key:
security_headers - Category:
SECURITY
Why fixing this matters
These headers are some of the cheapest security wins on the web. They reduce exposure to clickjacking, MIME sniffing, over-sharing of referrer data, and loose browser feature access. They are not a substitute for secure code, but they meaningfully reduce the blast radius of common mistakes.
They also drift easily. One team adds a good header set in application middleware, another adds or removes something at CDN level, and the final response no longer matches what anybody thought was live.
Common reasons this check warns or fails
- A header exists but uses an obsolete or weak value.
- A reverse proxy or CDN strips one of the expected headers.
- Security middleware is enabled on some routes but not others.
- Production and staging header policies diverged.
- New infrastructure was launched with only part of the old header baseline copied over.
If you are not technical
- Ask for the live response headers from production, not config screenshots.
- Ask which system owns the final headers: app, server, reverse proxy, or CDN.
- Ask for one source of truth so the same baseline applies everywhere.
- Re-run Scavo and confirm the critical issue count drops to zero.
Technical handoff message
Copy and share this with your developer.
Scavo flagged Security Headers (security_headers). Please inspect the live response headers on the affected route, fix any missing or weak critical values (X-Frame-Options, X-Content-Type-Options, Permissions-Policy, Referrer-Policy), and confirm the final production response matches the intended baseline.If you are technical
- Capture the final production headers from the real route and environment Scavo tested.
- Fix critical issues first: missing headers, invalid values, or weak policies.
- Use
X-Frame-Options: DENYorSAMEORIGINunless you have a very specific framing requirement. - Use
X-Content-Type-Options: nosniffexactly. - Use a deliberate
Referrer-Policy, typicallystrict-origin-when-cross-originunless you have a reason to expose more. - Make
Permissions-Policyintentional rather than blank or placeholder-only. - After the baseline is clean, add or improve recommended hardening headers such as CSP and the cross-origin isolation set.
How to verify
- Run
curl -I https://your-urland inspect the final response headers. - Confirm critical headers exist and use the expected values.
- Test representative routes, not just the homepage.
- Confirm CDN, WAF, and app layers are not fighting each other.
- Re-run Scavo and verify the critical issue count is zero.
What this scan cannot confirm
- It does not deeply validate full CSP or HSTS policy quality; those have their own dedicated checks.
- It does not prove your application code is free from XSS, CSRF, or auth flaws.
- It cannot see private edge rules or environment-specific routes that were not part of the scan.
Owner checklist
- [ ] Assign one owner for final browser-security headers.
- [ ] Keep the baseline header policy version-controlled.
- [ ] Test headers at the final response layer, not just in framework config.
- [ ] Revalidate after CDN, WAF, proxy, or platform changes.
FAQ
Why can this pass even if some recommended headers are missing?
Because this check prioritizes critical baseline protection first. Missing recommended headers are still useful hardening work, but they do not always mean the basic setup is broken.
Why is a header value important if the header already exists?
Because some headers only work when set to specific values. A present-but-wrong value can create a false sense of safety.
Does this replace CSP and HSTS checks?
No. This is the broad baseline check. CSP and HSTS still need their own deeper validation.
Should every route send exactly the same headers?
Not always, but the security intent should be consistent and documented. Random variation between routes is usually a drift problem, not a design choice.
Sources
- OWASP HTTP Headers Cheat Sheet
- MDN: X-Frame-Options
- MDN: X-Content-Type-Options
- MDN: Referrer-Policy
- W3C Permissions Policy
Need a single header baseline mapped to your app and CDN layers? Send support one live response and which layer you think currently owns the headers.