A Default-Deny Dive at the Prompt Layer

HTTP response headers are a cheap, fast layer of security that browsers enforce for you — reachable defense that costs nothing once set from a config file. Getting the header set right prevents entire attack classes at the prompt layer, and it is the first thing a manual review checks. This lesson is the header set that a modern, secure site should serve, what each does, and the traps in configuring them.

The Core Seven

  • Content-Security-Policy (CSP): the heavyweight. Declares where scripts, styles, images and frames may come from; a default-src 'self'; script-src 'self' policy blocks inline scripts, eval, and third-party junk, which cuts most XSS payloads. Use script-src 'self' with nonces or hashes for the scripts you legitimately load; avoid the unsafe-inline escape hatch.
  • Strict-Transport-Security (HSTS): max-age=63072000; includeSubDomains tells browsers "use HTTPS for this domain for 2 years" — converting the first-visit upgrade from a possibly-stripped redirect into a guaranteed one. Enable it only after HTTPS is solid everywhere, and watch the preload directive.
  • X-Frame-Options / frame-ancestors: DENY or SAMEORIGIN stops clickjacking via <iframe> embedding; the CSP frame-ancestors directive is the modern equivalent.
  • X-Content-Type-Options: nosniff forces the browser to respect the served Content-Type instead of sniffing — killing a whole class of MIME-confusion attacks.
  • Referrer-Policy: strict-origin-when-cross-origin stops leaking full URLs (and tokens in URLs) to other sites while keeping useful referers first-party.
  • Permissions-Policy: gates device/feature access (camera=(), geolocation=()) per origin.
  • Cross-Origin-Opener/Resource Policies (COOP/COEP): harden against cross-origin leaks and Spectre-adjacent side-channel data reads for sites that run untrusted content.

Configuring Without Breaking the Site

Headers break things when misconfigured, and breaking your own page is the reason CSP is feared. Roll out CSP in report-only mode first: Content-Security-Policy-Report-Only logs violations to a reporting endpoint without blocking, letting you fix gaps before enforcement. HSTS should come after your HTTP fallbacks die, and add includeSubDomains only after your CDN serves everything over HTTPS. And remember the header is applied where you set it — behind a CDN/proxy you set it at the edge (nginx, Cloudflare), because backend headers are rewritten by the proxy layer.

Check Yours in One Command Today

Audit live servers with the browser's DevTools or a header-checking service; locally, curl -sI https://yoursite.example shows the header set in seconds. Every diff against the recommended set is a legitimate finding worth tracking in your review checklist. Set them once, verify repeatedly, and let the tightest configuration you can defend be the branch default: security headers are the cheapest full-framework security control a page ships, and missing them is among the most common trivial findings in any pentest report. When you adopt a framework, its own header preset is a starting point, not an approval — every preset contains defaults chosen for the average site, so diff your real response against the set you intend, and make the header test part of every release checklist rather than waiting for the annual audit cycle to find a missing header.