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
My site got 100 in Vercel’s Is Agentic agent-ready scoring tool – here’s how
Two scanners graded my site on how usable it is by AI agents. The highest-scoring thing I added was a text file saying my site has no login.
WordPress Core AI in Practice: From the Abilities API to Claude as an Agent
WordPress now has two AI systems that point in opposite directions: one where WordPress calls an AI, and one where an AI calls WordPress. Here's how each actually works as of WordPress 7.1, and why the Abilities API sitting underneath them is the part that matters.