HTTP Security Headers Explained: HSTS, CSP, Frame Ancestors, and More

By Huzaifa • Published: 2026-10-19 • 6 min read

A practical breakdown of eight essential HTTP response security headers—what attacks each directive mitigates, common misconfigurations, and how to audit your headers locally.

HTTP Security Headers Explained: HSTS, CSP, Frame Ancestors, and More cover image

Every time a browser loads a web page, the server sends HTTP response headers before the HTML body arrives. Several of those headers act as direct instructions to the browser's security model—controlling whether plain HTTP connections are permitted, which scripts are allowed to execute, whether your page can be embedded inside an invisible <iframe>, and which hardware APIs scripts on the page may request.

Configuring HTTP security headers does not replace input validation or parameterized database queries, because headers cannot fix a broken server endpoint. What they provide is defense in depth: even if a subtle markup bug or third-party script issue slips into a page, strict browser policies restrict what an attacker can accomplish.

Inspecting Your Current Response Headers

You do not need an external scanner to read a site's HTTP headers. Open your browser's Developer Tools (F12), switch to the Network tab, reload the page, click the main document request at the top of the waterfall, and copy the Response Headers block. You can also fetch headers from a terminal with curl -I https://example.com.

Once you have the raw header lines, paste them into the Security Headers Checker to audit eight core security policies locally in your browser, or use the HTTP Header Analyzer to inspect caching rules, Set-Cookie attributes, and general protocol headers alongside them.

1. Strict-Transport-Security (HSTS)

Even when your server redirects http:// requests to https:// with a 301 status, a user typing example.com into the address bar for the first time still makes one initial unencrypted HTTP request. On an untrusted Wi-Fi network, an active attacker can intercept that first request before the redirect happens (an SSL-stripping attack).

Sending Strict-Transport-Security tells the browser to upgrade every future connection to HTTPS automatically before sending a single packet over port 80:

Strict-Transport-Security: max-age=31536000; includeSubDomains
  • max-age=31536000 instructs the browser to remember HTTPS-only enforcement for one year (in seconds). Very short values like max-age=300 leave long gaps where the policy expires between visits.
  • includeSubDomains applies the same rule to every subdomain. Before adding it—and especially before adding the preload directive—verify that no legacy internal or staging subdomain still relies on plain HTTP, otherwise browsers will refuse to connect to that subdomain.

2. Content-Security-Policy (CSP)

Cross-Site Scripting (XSS) remains one of the most damaging browser vulnerabilities because injected JavaScript runs with full access to the origin's DOM and session context. Content-Security-Policy lets you declare an allowlist (or cryptographic nonces and hashes) for scripts, styles, images, network connections, and frames.

A strong starting policy for a self-hosted web application looks like this:

Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; upgrade-insecure-requests

Two common pitfalls weaken CSP in practice:

  • Including 'unsafe-eval' inside script-src re-enables eval() and new Function(), making script injection significantly easier to exploit.
  • Including 'unsafe-inline' inside script-src without nonces allows any injected <script> block or inline onerror= attribute to execute.

When rolling out CSP on an existing site that loads analytics, fonts, or ad scripts, start with Content-Security-Policy-Report-Only first. That header logs violations in the browser console without blocking legitimate assets while you refine your directives.

3. Clickjacking Protection: frame-ancestors and X-Frame-Options

In a clickjacking (UI redressing) attack, a malicious page loads your authenticated web app inside a transparent <iframe> positioned directly over a decoy button, tricking a signed-in user into clicking "Delete", "Approve", or "Transfer" on your site without realizing it.

Modern browsers enforce CSP's frame-ancestors directive (frame-ancestors 'none' or frame-ancestors 'self'). Adding the classic X-Frame-Options header alongside it ensures consistent behavior across older clients and audit tools:

X-Frame-Options: DENY

Use SAMEORIGIN instead of DENY only if your own pages legitimately embed other pages from the exact same origin inside iframes.

4. X-Content-Type-Options: nosniff

Historically, browsers tried to be helpful by "MIME sniffing"—inspecting the first few bytes of a downloaded file and guessing its type even when the server sent Content-Type: text/plain. If users can upload text files or avatars, MIME sniffing can trick a browser into executing a disguised file as HTML or JavaScript.

There is only one valid value for this header, and nearly every site should send it on all responses:

X-Content-Type-Options: nosniff

Once nosniff is active, make sure your server sends accurate Content-Type headers (text/javascript for scripts and text/css for stylesheets), because browsers will strictly refuse to execute mismatched types.

5. Referrer-Policy

When a visitor clicks an outbound link or your page fetches a third-party image, the browser sends a Referer request header. If your application places reset tokens, search queries, or document IDs inside URL paths or query strings, an overly permissive referrer policy leaks that full URL to external domains.

The modern browser default—and a sensible explicit header to set—is:

Referrer-Policy: strict-origin-when-cross-origin

This sends the full path on same-origin navigations (preserving your own internal analytics), sends only the bare origin (https://example.com/) when navigating to another HTTPS site, and sends nothing at all if a link downgrades from HTTPS to HTTP. Avoid unsafe-url, which leaks full URLs even across protocol downgrades.

6. Permissions-Policy

Formerly called Feature-Policy, Permissions-Policy disables powerful browser APIs that your site does not need—and prevents embedded third-party iframes from requesting them without explicit delegation:

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

An empty allowlist () blocks access even for scripts on your own origin, reducing the blast radius of any compromised third-party dependency.

7. Cross-Origin Isolation: COOP and CORP

Two newer headers protect applications from cross-window references and unintended cross-origin resource embedding:

  • Cross-Origin-Opener-Policy: same-origin (COOP) isolates your browsing context group so cross-origin popups cannot retain a window.opener reference to your tab. Note that if your app uses OAuth login popups (like Google Sign-In popups that communicate back to the parent window), same-origin-allow-popups is often required instead of strict same-origin.
  • Cross-Origin-Resource-Policy: same-origin or same-site (CORP) instructs browsers not to load your private API responses or user images into cross-origin <img> or <script> tags unless explicitly marked cross-origin (for public CDN assets).

Putting Together a Clean Baseline

Before deploying header changes to production, test your full response block in a staging environment—checking login flows, embedded videos, and third-party scripts—and verify the resulting header set with the Security Headers Checker to confirm no typos or weak directives slipped through.

Featured Tools Mentioned in This Guide

  • Security Headers Checker — Paste raw HTTP response headers to audit CSP, HSTS, X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy, COOP, and CORP locally.
  • HTTP Header Analyzer — Parse, inspect, and analyze raw HTTP request/response headers for security flags and caching.