WhoDNS
All articles
Language: FA

HTTP Security Headers: The Seven Headers Every Site Should Send

Security headers are instructions your web server attaches to every response, telling the browser which attacks to refuse on your behalf. They require no application changes — usually a few lines in nginx, Apache or your hosting panel — yet they neutralise whole classes of exploits. The seven worth shipping:

  • Strict-Transport-Security (HSTS): forces the browser to use HTTPS on future visits, even if a user types the bare HTTP address. Pair it with a permanent redirect from HTTP.
  • Content-Security-Policy: whitelists where scripts, styles and frames may load from. The single strongest defence against cross-site scripting (XSS).
  • X-Content-Type-Options: nosniff: stops the browser from guessing a file type. Without it, an uploaded file served as text can end up executing as script.
  • X-Frame-Options: DENY or CSP frame-ancestors: stops your pages being framed by another site, which defeats clickjacking.
  • Referrer-Policy: controls how much of your internal URLs leaks to third-party sites through the Referer header. strict-origin-when-cross-origin is a sane default.
  • Permissions-Policy: denies camera, microphone and geolocation access unless you explicitly allow it.
  • Hardened cookies: every session cookie needs the HttpOnly, Secure and SameSite flags, so scripts cannot read it and it never travels over plain HTTP.

Values you can copy

A realistic starting point for an nginx site:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; object-src 'none'; base-uri 'self'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Start HSTS with a modest max-age (for example 86400, one day) while you confirm every subdomain works over HTTPS, then raise it to 31536000. A broken subdomain under a long HSTS policy is unreachable for the policy duration, so raise the number only after testing.

Deploying CSP without breaking the site

CSP is the header most likely to break things, so stage it. Ship it first in report-only mode — Content-Security-Policy-Report-Only — and watch the console: the browser lists every resource the policy would block without actually blocking anything. Tighten script-src until the noise stops, then flip the real header. Avoid unsafe-inline and unsafe-eval where you can; if inline scripts are unavoidable, use nonces or hashes instead.

Common mistakes

  • Protecting only the main domain: HSTS with includeSubDomains covers subdomains, but the header itself must also be sent by API and CDN hostnames you serve from other origins.
  • Setting the header on HTML pages only: if a redirect to the login page lacks the headers, the protection is lost on that hop. Send them on every response, including 301s, 404s and errors — that is what the always flag in nginx does.
  • Forgetting cookies: headers protect the browser; cookies need their own flags. A session cookie without HttpOnly is readable by any injected script, defeating even a perfect CSP.
  • Trusting the server-side check: frameworks and caches rewrite response headers unpredictably. A header present on localhost may be absent in production.

Headers are also easy to lose: a reverse proxy, a CDN or an application framework can strip or override them silently. Verify from the outside, not from the server itself. The WhoDNS headers tool fetches your URL over the network and shows every response header, so you can confirm all seven are present on the live site — including on redirect targets, which are easy to forget.

🔗 Related tool: Check the HTTP security headers of any site

security headersCSPHSTSX-Frame-OptionsX-Content-Type-OptionsReferrer-Policy