DEV Community

Cover image for Four HTTP security headers every WordPress site should set
Jeremy Burgos
Jeremy Burgos

Posted on • Originally published at webstackdefense.com

Four HTTP security headers every WordPress site should set

TL;DR: Four response headers, a few minutes of work, most of the header-level security gap closed. Exact values below, plus a one-line curl to check any site.

Run this against your own site first:

curl -I -s https://yoursite.com | grep -i -E 'strict-transport|x-content|x-frame|referrer'
Enter fullscreen mode Exit fullscreen mode

Whatever does not come back is your to-do list. These four headers are public on every request and contain nothing sensitive, so you can check mine, I can check yours, and neither of us has to log into anything. Here is what each one is and the value I actually run in production.

terminal curl output

Strict-Transport-Security

strict-transport-security: max-age=31536000; includeSubDomains; preload
Enter fullscreen mode Exit fullscreen mode

Tells the browser to use HTTPS for your domain, full stop, for the max-age window. Once a browser has seen it, typing http:// does nothing; the browser refuses to send the insecure request. max-age=31536000 is one year. includeSubDomains pushes the rule to every subdomain, closing the gap where an attacker targets some forgotten staging host. preload is the part people skip, and it matters: without it, the very first request before the browser has ever seen your header can still go out over HTTP, and that first request is the attack window. Preloaded domains skip it because the browser ships already knowing your domain is HTTPS-only. Submit once at hstspreload.org, it is free, and inclusion rides the Chromium release train so it takes a few weeks.

X-Content-Type-Options

x-content-type-options: nosniff
Enter fullscreen mode Exit fullscreen mode

Browsers used to guess at content types when the server was vague, which is exploitable. nosniff tells the browser to trust the declared Content-Type and stop guessing. There is no other value and nothing to tune. If your production site is missing this, you can fix it before you finish this article.

X-Frame-Options

x-frame-options: SAMEORIGIN
Enter fullscreen mode Exit fullscreen mode

Your clickjacking defense. It stops someone loading your real, logged-in site in an invisible iframe and floating their own buttons over it. SAMEORIGIN allows only your own pages to frame your site. DENY blocks all framing including yours, which is wrong if your WordPress setup uses internal iframes (Elementor previews, some widgets). The modern successor is CSP's frame-ancestors; run both during the transition, X-Frame-Options for older clients, CSP for the rest.

Referrer-Policy

referrer-policy: strict-origin-when-cross-origin
Enter fullscreen mode Exit fullscreen mode

Controls what your site leaks about users when they click away. strict-origin-when-cross-origin sends the full URL on same-origin requests so your analytics still work, only the origin on cross-origin HTTPS so you are not leaking that someone was on /account/billing, and nothing on cross-origin HTTP. Set it explicitly so you are not at the mercy of whatever default the next browser release ships.

Verifying

The curl above is the fastest check; all four lines should come back. In a browser, DevTools, Network tab, click the document request, read Response Headers. For a letter grade, securityheaders.com scores you against a known rubric. One quirk: these four alone land a B, and you reach A only once you add Content-Security-Policy.

security headers result example

dev tools example

These four are the floor. The next layer is Permissions-Policy and CSP in report-only mode. But if you only ever do these four, you have closed most of the gap, in minutes.

Originally published at https://www.webstackdefense.com/security-headers-production-websites/

Top comments (0)