Checking and hardening website security headers like CSP and HSTS

KI-Buster Blog · Cybersecurity

Website Security Headers Explained: CSP, HSTS, and More

HTTPS alone doesn't make a website fully secure. HTTP security headers give the browser extra rules to enforce, and they can help defend against cross-site scripting, clickjacking, and insecure connections. This guide covers which security headers matter, how to test them, and what to watch out for with CSP, HSTS, and more.

Published and fact-checked August 27, 2026

A valid SSL certificate is table stakes today. But HTTPS is only one part of a securely configured website.

Modern browsers support a whole range of so-called HTTP security headers. Through them, a web server can tell the browser things like:

  • which sources JavaScript is allowed to load from
  • whether the site may be displayed inside someone else's iframe
  • whether connections must always go over HTTPS
  • which browser features a page is allowed to use
  • how much referrer information gets sent when a user clicks through to another site

Correctly configured security headers can add a meaningful extra layer of defense against several classes of attack. OWASP explicitly recommends using appropriate HTTP response headers as part of a secure web application — see the OWASP HTTP Headers Cheat Sheet. They don't replace secure coding, patching, a firewall, or TLS — they add browser-level protection on top of those measures. The same least-privilege thinking applies to other privileged interfaces in your stack — for example an MCP server that gives an AI agent access to real systems. How to Operate MCP Servers Securely: Permissions, Tools, and Risks Explained (Read article)

The good news: you can check the security headers of pretty much any publicly reachable website within seconds. A very similar principle applies to checking a domain's email security. SPF, DKIM, and DMARC Explained Simply: Check Your Email Security (Read article)

What are HTTP security headers?

Every time a browser loads a website, it communicates with the web server over HTTP or HTTPS.

The server doesn't just deliver HTML, images, or JavaScript. Before the actual content, it sends a set of HTTP response headers.

A simplified example:

HTTP/2 200
content-type: text/html
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
content-security-policy: default-src 'self'

Some of these headers carry information about the resource being delivered. Others define rules the browser should follow when handling the site.

That's exactly where security headers come in.

Which website security headers matter?

For most websites and web applications, these headers matter most:

Security headerJob
Content-Security-PolicyRestricts which resources and scripts are allowed
Strict-Transport-SecurityEnforces HTTPS
X-Content-Type-OptionsPrevents MIME-type sniffing
X-Frame-OptionsProtects against clickjacking
Referrer-PolicyControls referrer data sent to other sites
Permissions-PolicyRestricts browser features
Cross-Origin-Opener-PolicyIsolates browsing contexts

Not every website needs exactly the same setup. Content Security Policy and the cross-origin headers in particular have to be tailored to the specific application.

1. Content Security Policy – CSP explained

Content Security Policy, or CSP, is one of the most powerful security headers around.

The header is:

Content-Security-Policy

With a CSP, the site owner defines which resources the browser is allowed to load or execute.

Mozilla describes CSP as a mechanism that can reduce the risk of cross-site scripting and other kinds of injected content.

A very simple policy might look like this:

Content-Security-Policy: default-src 'self';

In simplified terms, 'self' means:

Resources may only load from the same origin by default.

A more elaborate policy might look like this:

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

That restricts several different areas separately.

Common CSP directives

  • default-src
  • script-src
  • style-src
  • img-src
  • font-src
  • connect-src
  • frame-src
  • frame-ancestors
  • object-src
  • base-uri
  • form-action

One that matters a lot in practice:

frame-ancestors 'none'

That prevents other sites from embedding your page in a frame or iframe. The frame-ancestors directive is specifically designed to control this kind of embedding.

Careful: don't just copy a CSP from somewhere

Of all the security headers, a careless CSP is probably the fastest way to break parts of your site.

Websites often load content from:

  • Google Analytics
  • Google Fonts
  • content delivery networks
  • payment providers
  • map services
  • YouTube
  • ad networks
  • external APIs
  • consent managers
  • JavaScript libraries

Simply enabling

default-src 'self'

can end up blocking large chunks of your site.

Test your CSP first

You can test a policy first using this header:

Content-Security-Policy-Report-Only

Report-only mode lets you evaluate a CSP without actually enforcing the policy yet. Mozilla explicitly recommends this mechanism for testing and analyzing possible CSP violations.

For production systems, the workflow should be:

develop the CSP → test it → analyze violations → tighten it gradually → only then enforce it.

This matters especially if you're having ChatGPT suggest a CSP for you: never move a generated policy straight into production without review. For when to critically question AI output in system administration more broadly, see When to Question AI Output in System Administration (Read article).

2. Strict-Transport-Security – HSTS explained

The second especially important header is:

Strict-Transport-Security

Short for: HSTS – HTTP Strict Transport Security.

HSTS tells a browser that a website should only ever be accessed over HTTPS.

An example:

Strict-Transport-Security: max-age=31536000

max-age is given in seconds.

31,536,000 seconds is roughly one year.

With:

Strict-Transport-Security: max-age=31536000; includeSubDomains

the rule also applies to subdomains.

Browsers remember the HSTS information and try to connect over HTTPS directly on future visits. Certificate problems on known HSTS hosts are also treated more strictly.

What does HSTS preload mean?

You'll often see a configuration like this:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

That's how a domain gets prepared for an HSTS preload list in the first place.

In simplified terms: supporting browsers can already know a domain should only ever be reached over HTTPS, even before they've visited that site for the first time.

That sounds great — but it's a decision with real consequences.

Don't flip on includeSubDomains and preload lightly

Before using these options, make sure that:

  • the main domain actually supports HTTPS
  • every relevant subdomain supports HTTPS
  • certificates are renewed reliably
  • no old applications are reachable only over HTTP

Google also warns against enabling HSTS before HTTPS operation is reliably stable, and recommends starting with a lower max-age value.

A misconfigured HSTS setup can make certain systems completely unreachable for users.

3. X-Content-Type-Options

This header is much simpler:

X-Content-Type-Options: nosniff

It prevents so-called MIME-type sniffing.

Browsers should respect the content type declared by the server instead of trying to guess a different file type on their own. Mozilla explicitly names nosniff as a defense against MIME-type sniffing.

For many websites, this header is a sensible part of the baseline configuration.

4. X-Frame-Options

The header:

X-Frame-Options

controls whether a website may be displayed inside a frame.

Common settings are:

X-Frame-Options: DENY

or:

X-Frame-Options: SAMEORIGIN

DENY: the page may never be displayed in a frame at all.

SAMEORIGIN: the page may only be shown in a frame from the same origin.

That specifically helps reduce the risk of clickjacking attacks.

Mozilla documents X-Frame-Options as a mechanism for controlling how a page can be displayed in frames.

In modern applications, you should also look at the CSP frame-ancestors directive, which allows much more precise rules.

5. Referrer-Policy

When a user clicks a link, the browser can send information about which page they came from.

You can control how much of that gets shared with this header:

Referrer-Policy

A commonly sensible setting is:

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

That controls how much information is sent for same-origin versus cross-origin requests.

Mozilla describes Referrer-Policy precisely as the mechanism for controlling the information sent in the Referer header.

6. Permissions-Policy

Modern browsers expose a whole range of powerful APIs.

For things like: camera, microphone, geolocation, fullscreen mode, sensors, payment features.

Using:

Permissions-Policy

a website can define which of these features are allowed to be used.

Example:

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

That disables camera, microphone, and geolocation for the document.

Mozilla describes Permissions-Policy as a mechanism for allowing or denying browser features for both the document itself and any embedded frames.

Here too: don't just disable everything blindly.

A site with a map feature probably needs geolocation. A video-conferencing app needs camera and microphone. The policy has to fit the application.

7. Cross-Origin-Opener-Policy and other modern headers

In more complex web applications, you'll also run into headers like:

Cross-Origin-Opener-Policy
Cross-Origin-Embedder-Policy
Cross-Origin-Resource-Policy

For example:

Cross-Origin-Opener-Policy: same-origin

COOP can isolate browsing contexts from one another. Mozilla describes the header as a way to control whether different top-level documents run within the same browsing context group.

These headers can be extremely valuable for modern applications.

But they can also affect external logins, pop-ups, embedded content, APIs, and external resources.

That's why they tend to fall into the "advanced security hardening" category.

Checking website security headers with curl

On Linux, macOS, and many Windows systems, curl alone is enough.

Example:

curl -I https://example.com

That returns the HTTP response headers.

Often more informative is a normal GET request where you only print the headers:

curl -s -D - -o /dev/null https://example.com

Then look for entries like:

content-security-policy
strict-transport-security
x-content-type-options
x-frame-options
referrer-policy
permissions-policy

Checking security headers on Windows with PowerShell

You can also read HTTP headers with PowerShell:

$response = Invoke-WebRequest -Uri "https://example.com"
$response.Headers

Alternatively, on current Windows systems you can use curl.exe:

curl.exe -I https://example.com

This approach works great for admins who want to check multiple sites in an automated way.

Checking security headers directly in the browser

You don't even need an extra tool for this.

In Chrome, Edge, or Firefox:

  1. Open the website.
  2. Open developer tools.
  3. Switch to the Network panel.
  4. Reload the page.
  5. Select the main document.
  6. View the response headers.

You'll find entries like:

content-security-policy
strict-transport-security
x-frame-options
x-content-type-options

Especially when troubleshooting CSP issues, it's worth checking the browser console too — blocked scripts or resources usually show up there.

Testing security headers with online tools

If you'd rather not use a command line, you can also have your website analyzed automatically.

Two well-known options:

Mozilla HTTP Observatory: Mozilla's HTTP Observatory scans a site's CSP, HSTS, and other security settings and offers concrete improvement suggestions.

SecurityHeaders.com: SecurityHeaders.com focuses specifically on analyzing HTTP response headers and gives you a quick overview of what's present and what's missing.

A good test result is helpful, but it doesn't automatically mean a website is secure overall.

Security headers are just one layer of web security.

Why an A+ security-header rating doesn't automatically mean a secure website

This is a really important point.

A website can have perfect security headers and still, for example:

  • run outdated WordPress plugins
  • use weak passwords
  • be vulnerable to SQL injection
  • have broken access permissions
  • use insecure session cookies
  • expose vulnerable APIs
  • rely on vulnerable JavaScript libraries

Security headers are not a security guarantee.

They're one piece of a defense-in-depth approach.

Configuring security headers on Nginx

On Nginx, headers can be added like this:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000" always;

A CSP could additionally read something like:

add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self';" always;

Important: this CSP is only an example and shouldn't be dropped unmodified into a production system.

With Nginx especially, also verify which headers actually reach the client. Reverse proxies, nested locations, load balancers, or CDNs can all change the final response.

Configuring security headers on Apache

With Apache and mod_headers, a configuration like this is possible:

<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=31536000"
</IfModule>

A CSP could additionally be defined:

Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self';"

Same rule here: test first, then enable in production.

Configuring security headers on Microsoft IIS

On IIS, headers can be added via web.config:

<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
<add name="Strict-Transport-Security" value="max-age=31536000" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>

Alternatively, headers can be set centrally through IIS Manager or on an upstream reverse proxy.

For larger infrastructures, centralizing this often makes sense — on Nginx, HAProxy, IIS ARR, Apache, Cloudflare, an application gateway, or a CDN. For how I use ChatGPT more generally for configuration and diagnostic work like this in Linux administration, see How I Use ChatGPT for Linux Administration (Read article).

What matters in the end isn't where the header gets set. What matters is which header actually reaches the browser.

Checking security headers behind HAProxy or a reverse proxy

Larger infrastructures often have several layers:

Internet
↓
CDN / WAF
↓
HAProxy / load balancer
↓
Nginx / IIS / Apache
↓
Web application

Headers can be added, overwritten, stripped, or duplicated at any of these layers.

So you should never rely solely on checking the backend server's own configuration.

Always test the publicly reachable URL.

Example:

curl -s -D - -o /dev/null https://www.example.com

That way you're checking the response exactly as a visitor would receive it.

Common mistakes with website security headers

Mistake 1: copying a CSP straight from the internet

Every website uses a different mix of resources. A CSP copied from somewhere else almost never fits your own application exactly.

Mistake 2: enabling HSTS with subdomains right away

includeSubDomains can make old subdomains unreachable if they don't support HTTPS yet.

Mistake 3: HSTS preload without planning

A preload configuration should only be used once full HTTPS operation is reliably stable.

Mistake 4: only testing the homepage

Headers can differ depending on the URL, application, backend, virtual host, or reverse proxy. So test paths like /, /login, /admin, /api/, /shop/, and /contact as well.

Mistake 5: only checking whether headers exist

A header being present doesn't automatically make it a good header.

Example:

Content-Security-Policy: *

would technically count as a policy, but it wouldn't provide the protection you're after.

What matters is both: is the header present? and: is its content actually meaningful?

A recommended security-header baseline

For a typical website, a reasonable starting point might look like this:

Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()

On top of that, add a Content Security Policy tailored to your specific website.

One more time: these values aren't a universal copy-paste config.

Web applications with external APIs, payment providers, embedded videos, SSO, maps, or other integrations may well need different settings.

The OWASP Secure Headers Project lists recommended configurations and typical use cases for the various security headers.

Do security headers affect SEO?

This question often gets answered incorrectly.

CSP, X-Frame-Options, and Permissions-Policy are not magic SEO ranking factors.

You shouldn't install security headers hoping to gain a few ranking points.

The picture looks different when it comes to running a website securely overall.

Google treats HTTPS as a positive signal and explicitly recommends that site owners serve their pages securely. Google's current page experience guidance also explicitly asks whether pages are served securely.

So the real relationship looks more like this:

security headers → better technical hardening → lower risk of compromised content → more trust and a more stable site → a positive foundation for both users and search engines.

A hacked website full of spam pages, malware, or manipulated redirects, on the other hand, can cause serious SEO damage. Google's spam policies explicitly cover content and redirects injected by attackers too.

So security absolutely matters for SEO — just not as a simple "add a header, get a ranking boost" trick.

Monitoring security headers over time

A one-time test isn't enough in the long run.

Websites keep changing: new plugins, new tracking tools, new APIs, server migrations, CDN switches, reverse-proxy changes, CMS updates, new subdomains.

A security configuration that works well today might no longer be optimal a few months from now.

For business-critical systems, it's worth monitoring headers automatically — for example, curl combined with cron, PowerShell, GitHub Actions, GitLab CI/CD, Jenkins, Checkmk, Zabbix, or Nagios.

That lets you check, for instance, whether Strict-Transport-Security, Content-Security-Policy, and X-Content-Type-Options are still in place.

Website security header checklist

Before you call it done, check the following:

  • Website fully reachable over HTTPS
  • HTTP cleanly redirected to HTTPS
  • Strict-Transport-Security checked
  • Impact of includeSubDomains understood
  • HSTS preload used only deliberately
  • X-Content-Type-Options: nosniff present
  • Clickjacking protection checked
  • X-Frame-Options or CSP frame-ancestors checked
  • Referrer-Policy defined
  • Permissions-Policy matched to the browser features you actually need
  • Content Security Policy built for your specific site
  • CSP tested first
  • External scripts and APIs accounted for
  • Browser console checked for CSP violations
  • Publicly reachable URL tested, not just the backend
  • Multiple subpages checked
  • Headers retested after any changes

Frequently asked questions about website security headers

What are security headers?

Security headers are HTTP response headers a web server uses to give the browser additional security rules. They can, for example, define which scripts are allowed to load or whether a site should only ever be reached over HTTPS.

How can I check a website's security headers?

The easiest way is with:

curl -I https://example.com

You can also use your browser's developer tools, Mozilla HTTP Observatory, or SecurityHeaders.com.

Which security header matters most?

There's no single answer that fits every site. HSTS, Content Security Policy, and X-Content-Type-Options are all particularly important. The right combination depends on the specific web application.

What does a Content Security Policy do?

A CSP defines which resources and origins a website is allowed to use. That can significantly reduce the risk of unwanted or injected scripts.

What does HSTS do?

HSTS tells browsers to only ever reach a domain over HTTPS going forward. Among other things, that prevents a user from accidentally falling back to an unencrypted HTTP connection.

Can a bad CSP break my website?

Yes. An overly restrictive policy can block JavaScript, stylesheets, fonts, APIs, videos, or tracking systems. That's why a CSP should be thoroughly tested before it goes live.

Conclusion: security headers are part of a website's technical baseline

Running a website over HTTPS alone is important — but that's not where modern website security ends.

Security headers give administrators and developers extra ways to enforce protections directly in the browser.

The ones that matter most: Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and Permissions-Policy.

With a simple:

curl -I https://your-domain.com

you can get a first overview within seconds.

That's when the real work begins, though: not setting as many headers as possible, but configuring the right headers with rules that actually make sense.

Especially with CSP and HSTS: a configuration that's been tested and fits your own infrastructure is worth far more than a supposedly perfect template copied from the internet.

If you run a website professionally, you should check its security headers just as routinely as you check SSL certificates, updates, backups, and server logs.

Related reading

SPF, DKIM, and DMARC Explained Simply: Check Your Email Security (Read article)

How to Operate MCP Servers Securely: Permissions, Tools, and Risks Explained (Read article)

When to Question AI Output in System Administration (Read article)

How I Use ChatGPT for Linux Administration (Read article)

Sources and further technical documentation

Mozilla MDN – Content Security Policy. Mozilla MDN – Strict-Transport-Security. OWASP – HTTP Security Response Headers Cheat Sheet. OWASP Secure Headers Project. Google Search Central – HTTPS and secure site delivery. Mozilla HTTP Observatory – automated security header test.

As of: August 2026.