WP Front Door

The WordPress security headers the checker reads

Five response headers and HTTPS itself. Set them once at the server or CDN and every page carries them.

Written by . Updated . One of the security headers guides.

What the checker sees

The headers on the final response for the page. Plain HTTP is a problem. A missing Strict-Transport-Security, X-Content-Type-Options or framing protection is a warning. A missing Referrer-Policy or Content-Security-Policy is a note, because both need more care to add. Framing protection counts as present with either X-Frame-Options or a CSP containing frame-ancestors.

The checker reads whether each header is there, not how strict it is. A weak policy passes.

What each one does

  • Strict-Transport-Security tells browsers to use HTTPS for the site from now on, so a typed http:// address never leaves the browser unencrypted.
  • X-Content-Type-Options: nosniff stops a browser treating an uploaded file as a script because its contents look like one.
  • X-Frame-Options: SAMEORIGIN stops other sites loading yours in a frame to trick clicks.
  • Referrer-Policy: strict-origin-when-cross-origin sends only your domain, not the full address, when a visitor follows a link away.
  • Content-Security-Policy lists where scripts, styles and frames may come from. It is the strongest of the five and the easiest to get wrong.

Set them at the server

The server or CDN is the best place: the headers then cover images, feeds and error pages as well as the pages WordPress builds. For nginx, in the server block:

nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
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;

One nginx catch: a location block with any add_header of its own drops every header set at the server level. Repeat them there, or use an include file.

For Apache with mod_headers:

Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
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"

From WordPress, when you cannot touch the server

PHP
<?php
add_action( 'send_headers', function () {
	header( 'X-Content-Type-Options: nosniff' );
	header( 'X-Frame-Options: SAMEORIGIN' );
	header( 'Referrer-Policy: strict-origin-when-cross-origin' );
} );

This only covers pages WordPress renders, and a page cache serves whatever headers it stored, so purge it after the change.

Two cautions

HSTS with includeSubDomains forces HTTPS on every subdomain, including old ones without a certificate. Check them first, and start with a short max-age such as 300 before moving to a year.

A strict Content-Security-Policy breaks most WordPress sites, because themes and plugins rely on inline scripts. A safe first policy that still counts is frame-ancestors 'self'; object-src 'none'; base-uri 'self'; upgrade-insecure-requests. Tighten it later with Content-Security-Policy-Report-Only to see what would break.

Check the fix

Shell
curl -sI https://example.com/ | grep -iE 'strict-transport|x-content-type|x-frame|referrer-policy|content-security'

Check a site for this

A domain or a full address. Only public pages are fetched, the way a browser would.