HTTP response reachable #
The header checks evaluate the response of a real page load (https://…/). If no HTTP response can be fetched – connection refused, timeout, or an invalid certificate aborting the request – there are no headers to grade.
Every response-header check of the headers module: what is tested, why it matters and how it is scored – from HSTS and CSP quality down to cookie flags and information leaks. Check your domain →
Last updated: July 2026 · 31 checks documented
The header checks evaluate the response of a real page load (https://…/). If no HTTP response can be fetched – connection refused, timeout, or an invalid certificate aborting the request – there are no headers to grade.
The scanner follows redirects before analyzing headers. If the chain ends on a different domain, all header findings describe that final host, not the scanned domain. If it ends on unencrypted http://, the entire page (content, cookies, logins) is exposed to man-in-the-middle attacks despite the HTTPS start.
http:// (HTTPS→HTTP downgrade); info if the redirect merely ends on another registrable domain. Not shown when the page stays on the scanned domain over HTTPS.http:// and serve the final page over HTTPS. For cross-domain redirects, scan the final domain directly for meaningful results.HSTS instructs the browser to access the domain exclusively over HTTPS from then on, preventing SSL-stripping/downgrade attacks as well as insecure first visits.
max-age=0 → fail, because that actively DELETES an existing HSTS policy in the browser. Weight 2.Strict-Transport-Security: max-age=63072000; includeSubDomains; preload (only after HTTPS is verified on all subdomains).Domains on the browsers’ HSTS preload list are addressed only over HTTPS from the outset – even on the very first visit, before any header is seen. This point checks two independent facts: (1) eligibility – does the current header meet the hstspreload.org criteria (max-age ≥ 1 year, includeSubDomains, preload)? and (2) list status – is the domain actually on the preload list, queried live from the official hstspreload.org status API? The critical case is being on the list while the header is no longer compliant (e.g. preload was removed later): shipping browsers still enforce HTTPS, but the entry becomes eligible for automatic removal – after which first-visit protection silently disappears – and the header should never have been changed without the official removal process.
max-age=63072000; includeSubDomains; preload unchanged; to leave the list, use hstspreload.org/removal/ rather than just dropping the header.The CSP is the most effective protection layer against cross-site scripting (XSS): it defines which sources may load scripts, styles, etc. A pure host allowlist with unsafe-inline is often bypassable; nonce-/hash-based policies with strict-dynamic are strong. The detail additionally reports whether the strict internet.nl criteria are met (no unsafe source in ANY directive incl. style-src, no http:/bare https:/wildcard hosts, restricted default-src/frame-ancestors/base-uri/form-action) – relevant for a 100% internet.nl score, without influence on the grade here.
strict-dynamic; avoid unsafe-inline/unsafe-eval (inline styles → CSS files or element.style/CSSOM).Three directives harden a CSP against injection beyond script sources: object-src 'none' blocks outdated plugin embeddings (<object>/<embed>). base-uri and form-action have NO fallback to default-src – without them set, an injected <base> tag can redirect relative URLs to a foreign server, and an injected <form action> can send data to foreign servers (phishing/exfiltration), even with a strict default-src.
object-src 'none'; base-uri 'none'; form-action 'self' to the CSP.Automatically upgrades insecure HTTP resource requests to HTTPS, thereby preventing mixed content. The older block-all-mixed-content is deprecated.
upgrade-insecure-requests to the CSP (replaces block-all-mixed-content).Trusted Types (require-trusted-types-for 'script') are the strongest protection layer against DOM-based XSS: dangerous DOM sinks then accept only vetted values.
require-trusted-types-for 'script' (+ trusted-types).The sandbox directive additionally restricts the document (like the iframe sandbox attribute). Caution: allow-scripts + allow-same-origin together largely defeat the sandbox.
allow-scripts + allow-same-origin. Weight 0.allow-scripts and allow-same-origin together.CSP violations can be reported – in the modern form via report-to <group> (references a defined reporting endpoint), in the deprecated form via report-uri <url>. If report-to references an undefined group, all reports are silently lost.
report-to; warn with report-to pointing to an undefined endpoint; info if only the deprecated report-uri is used. Weight 0.report-to to a group defined in Reporting-Endpoints (add report-uri as well for the transition).Prevents MIME sniffing – the browser then interprets responses strictly according to the declared Content-Type instead of "guessing", which blocks certain XSS tricks.
nosniff; otherwise fail. Weight 1.X-Content-Type-Options: nosniff.Prevents the page from being embedded in a foreign frame and abused for clickjacking – via X-Frame-Options or, in the modern form, via CSP frame-ancestors.
DENY/SAMEORIGIN or CSP frame-ancestors with none/self/host allowlist; warn with ALLOW-FROM (ignored by modern browsers) or frame-ancestors */scheme wildcard; fail if both are missing. Weight 1.X-Frame-Options: DENY or CSP frame-ancestors 'none' (frame-ancestors is the modern, more powerful option).Controls how much of the originating URL is sent to third parties when leaving the page. Some values are unsafe: unsafe-url always sends the full URL, and no-referrer-when-downgrade leaks it on an HTTPS→HTTP downgrade.
Referrer-Policy: no-referrer or same-origin; strict-origin-when-cross-origin is an acceptable minimum.Selectively disables powerful browser features (camera, microphone, geolocation …) and reduces the attack surface – including for embedded content. Allowlist syntax: () = off, self = own domain only, * = everywhere (risk), (self "https://…") = allowlist.
* on a core feature, a missing header, empty/permissive values, or outdated Feature-Policy syntax. Additional high-risk features (display-capture, serial, hid, bluetooth …) are also listed. Weight 1.(), e.g. Permissions-Policy: camera=(), microphone=(), geolocation=().COOP isolates the browsing context from cross-origin opened windows and makes XS-Leaks harder. The value is decisive: unsafe-none provides no protection. FULL cross-origin isolation (for SharedArrayBuffer/precise timers) additionally requires COEP require-corp/credentialless; CORP protects your own resources from being included by foreign sites. The COEP/CORP state is reported as context in the same finding – it is optional for many sites and potentially breaking.
same-origin can break OAuth/payment popups on ordinary sites. A protective COOP value (same-origin/same-origin-allow-popups) earns a green check (good); unsafe-none or a missing header is neutral info. Neither affects the grade. COEP/CORP are reported as context.Cross-Origin-Opener-Policy: same-origin if you rely on cross-origin isolation (SharedArrayBuffer, precise timers); for full isolation additionally Cross-Origin-Embedder-Policy: require-corp and appropriate CORP headers. Not required for a typical site.With Origin-Agent-Cluster: ?1, the page asks the browser to place it in an origin-isolated process. This makes Spectre-style side-channel attacks between origins harder.
Origin-Agent-Cluster: ?1.Document-Policy controls document-wide features (e.g. enforced image compression, oversized images) – related to the Permissions-Policy, but for document properties.
If an HTTPS page loads resources over http://, an attacker can tamper with them. Active mixed content (scripts/iframes/CSS) allows takeover of the page, while passive content (images) is often blocked.
upgrade-insecure-requests counts as a mitigation. Weight 1–2.upgrade-insecure-requests.Cross-origin included scripts/styles (e.g. from CDNs) without an integrity hash are vulnerable to supply-chain tampering: if the CDN is compromised, attacker code runs on the page.
integrity="sha384-…" crossorigin="anonymous" to cross-origin <script>/<link>.Enforces Subresource Integrity (SRI) for included resources – strong supply-chain protection that goes beyond the individual integrity attribute.
Integrity-Policy: blocked-destinations=(script).Cookies without Secure can be intercepted over HTTP; without HttpOnly they can be read via JavaScript (XSS); SameSite protects against CSRF.
Secure; HttpOnly; SameSite=Lax (or Strict).The name prefixes __Host- and __Secure- (RFC 6265bis) let the browser enforce cookie integrity: a __Secure- cookie must be set with Secure, a __Host- cookie additionally with Path=/ and without a Domain attribute. Violating cookies are silently discarded by browsers – the application then never receives them, which surfaces as mysterious login loops.
Secure (and for __Host-: Path=/, no Domain=) – or use the prefix deliberately: __Host-session=…; Secure; HttpOnly; SameSite=Lax; Path=/ is the most robust session-cookie form.Authenticated responses (with a session/auth cookie) should not be cached in proxies/browsers – otherwise subsequent users could see other people’s logged-in content.
no-store/private (to avoid false positives on public pages).Cache-Control: no-store (or private).A misconfigured CORS policy can allow foreign sites to read authenticated responses. A reflected (or *) origin combined with Access-Control-Allow-Credentials: true is dangerous.
* origin + credentials (reading authenticated data possible); info with * without credentials (usually fine for public assets). Only checked if ACAO is set.* with Allow-Credentials: true; use a strict origin allowlist instead.Controls whether Adobe clients (Flash/Acrobat) may access across domains via crossdomain.xml. Best practice is none. Real-world relevance is low (Flash is dead), but it is checked by scanners like securityheaders.com.
none; warn with all; info for any other value (e.g. master-only). Only evaluated when the header is set. Weight 0.X-Permitted-Cross-Domain-Policies: none.The browsers’ former XSS auditor has been removed and could itself cause security problems (XS-Leaks). The header should no longer be used actively.
1/1; mode=block – recommendation to remove it or set it to 0.0 (or remove it) and use a CSP instead.HPKP was meant to prevent certificate mis-issuance, but it was so dangerous (risk of permanently locking yourself out) that it was removed from all browsers.
Public-Key-Pins(-Report-Only) is set – the header should be removed.The Expect-CT header has been removed since Chrome 107 – Certificate Transparency is now enforced automatically. The header is superfluous.
Reporting delivers reports about CSP/COOP/network violations. There are two generations: Reporting-Endpoints (modern, preferred) and the deprecated Report-To (deprecated by Chrome). Important: NEL (Network Error Logging) works ONLY with Report-To, not with Reporting-Endpoints.
Report-To group that is not defined (reports are silently lost). Deprecated Report-To only → note about migrating.Reporting-Endpoints; for NEL, additionally define a matching Report-To group.Headers like Server: nginx/1.26.3 or X-Powered-By: PHP/8.2 reveal the software stack. A version number lets an attacker match known CVEs directly to the exact build – that is what matters and what gets downgraded. A bare product name (Server: nginx, AmazonS3, cloudflare, Apache) only says WHAT runs, not which version, so it cannot be mapped to a specific CVE and is treated as purely informational (no downgrade). A "version" means a dotted decimal (e.g. /1.26.3, 4.0.30319); a product name that merely contains a digit (AmazonS3, CDN node IDs) is not a version. Hiding banners entirely is hygiene (minimal disclosure), not a substitute for patching.
server_tokens off (hides the version) or remove entirely with the headers-more module (more_clear_headers Server); Express: app.disable("x-powered-by"); PHP: expose_php = Off.A /.well-known/security.txt provides contact channels for security reports and facilitates responsible disclosure of vulnerabilities. The file is validated against the MUST/SHOULD requirements of RFC 9116 the way internet.nl’s sectxt validator does: mandatory Contact (as a URI – a bare email address without mailto: is invalid, §2.5.3), exactly one Expires in RFC 3339 format that is not in the past (§2.5.5), text/plain with UTF-8 (§3), https:// for all web URIs, valid field syntax, at most one Preferred-Languages with valid tags, the mandatory /.well-known/ location (§3) and – if Canonical is present – that the retrieved URI is listed there (§2.5.2, otherwise the file should not be trusted). SHOULD requirements (Expires less than a year ahead, OpenPGP signature, Encryption key for email contacts) are reported as hints; the signature is checked structurally, not cryptographically.
/.well-known/security.txt with Contact: (mailto:/tel:/https: URI) and Expires: (RFC 3339, less than a year ahead), served as text/plain; charset=utf-8; if Canonical is used, list the exact retrieval URI. Validate e.g. with the internet.nl security.txt check.