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.
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=31536000instructs the browser to remember HTTPS-only enforcement for one year (in seconds). Very short values likemax-age=300leave long gaps where the policy expires between visits.includeSubDomainsapplies the same rule to every subdomain. Before adding it—and especially before adding thepreloaddirective—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'insidescript-srcre-enableseval()andnew Function(), making script injection significantly easier to exploit. - Including
'unsafe-inline'insidescript-srcwithout nonces allows any injected<script>block or inlineonerror=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 awindow.openerreference 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-popupsis often required instead of strictsame-origin.Cross-Origin-Resource-Policy: same-originorsame-site(CORP) instructs browsers not to load your private API responses or user images into cross-origin<img>or<script>tags unless explicitly markedcross-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.