back to writing
July 15, 2026

Security headers matter, so I created a plugin to improve this site’s score

Dries Buytaert, creator of Drupal and co-founder of Acquia, built a tool called headers.dev that analyzes the HTTP security headers on any website and gives it a score. I came...

Dries Buytaert, creator of Drupal and co-founder of Acquia, built a tool called headers.dev that analyzes the HTTP security headers on any website and gives it a score. I came across it recently and, naturally, ran it on miriamschwab.me.

My score was abysmal: 4 out of 10 due to nine missing headers.

What HTTP security headers are

HTTP security headers are instructions that your web server sends to browsers alongside your pages. They tell the browser how to behave – what content it can load, whether the page can be embedded in an iframe on another site, how much referrer information to pass along when someone clicks an outbound link. Most of them have no visible effect under normal use. They exist to constrain what a browser will do in edge cases – and in those edge cases, they make a real difference.

The ones my site was missing:

  • X-Content-Type-Options – Prevents browsers from guessing a file’s content type and potentially executing something unexpected
  • X-Frame-Options – Blocks clickjacking by preventing your site from being loaded inside an iframe on another domain
  • Referrer-Policy – Controls how much information about where your visitors came from gets passed along when they click outbound links
  • Permissions-Policy – Restricts which browser features (camera, microphone, geolocation) scripts on your pages can access
  • X-Permitted-Cross-Domain-Policies – Blocks Flash and PDF clients from loading cross-domain content

Plus a few others I deliberately didn’t add.

The plugin situation

The first thing I did was look for a plugin. The most well-known option, the “Security Headers” plugin, hadn’t been updated in seven years. There are newer alternatives but the functionality is simple enough that building a custom plugin made more sense for me for the long term.

So I built one. A settings page at Settings -> Security Headers lets me toggle each header on or off. Five headers are on by default with safe values. The sixth – Strict-Transport-Security – is off by default, because Cloudflare already sends that header and I didn’t want to create a potential conflict.

What I didn’t add

The remaining missing headers from my score are Content-Security-Policy and three cross-origin headers (COEP, COOP, and CORP).

CSP is the one with the highest real-world security value – a properly configured CSP can stop XSS attacks from doing damage even if a script gets injected. It’s also the hardest to implement correctly on a WordPress site. A proper CSP requires an accurate inventory of every script and style source the site loads. WordPress with Elementor generates inline scripts throughout the page, and getting that list right without breaking anything is a real project. Setting the policy to unsafe-inline defeats the entire purpose, so I left it out for now.

The three cross-origin headers exist to enable cross-origin isolation – something you’d need if you were using SharedArrayBuffer for high-resolution timing. A personal blog has no such requirements, and enabling them would likely break embedded content, Google Fonts (not in my case because I localized all the fonts for performance purposes – see my changelog), and other third-party resources.

My site’s score increased from 4 to 6

After installing the plugin, my score went from 4 to 6 out of 10. The four remaining missing headers are the ones I deliberately skipped. The two warnings in the report are controlled at the Cloudflare and Elementor Cloud layer, not something I can set from WordPress.

Six out of ten is roughly the practical ceiling for a WordPress site on managed hosting with Cloudflare. The remaining four missing headers are either too risky to add without significant testing (CSP) or irrelevant to what this site actually does (the cross-origin trio).

I haven’t made the plugin available yet due to security concerns, but you can see all my other available plugins and skills here: Miriam’s Plugins.

filed under

Other posts

all posts
How I improved by my site’s AI-Readiness score from 51 to 86
I’m a tiny bit obsessed with iterating my site to agenty-ready and web-optimized perfection. That’s why I’ve spent many sessions running my site against specification.website‘s checklist and fixing what it...
I wanted to be able to do more with AI on my site, so I gave Claude WP REST API access – with limitations
A conversation about why WordPress core still ships so few AI abilities and the limitations they have got me thinking: why am I making my site fully dependent on Abilities...