ISSUE 19 · 6 MIN READ ·

The security headers a library update quietly switched off

A routine dependency bump can silently stop your site sending its clickjacking and content-type protections. How to check your security headers in one minute.

You did the right thing when the site was built. The security headers were set — the small instructions your server sends with every page telling the browser how to behave: don’t let another site frame this page, don’t try to guess file types, only load over a secure connection. They were configured, they worked, and you moved on to the next thing.

Then, months later, someone bumped a dependency. Not a dramatic change — a routine update to a framework or a library, the kind you do without ceremony to stay current. Nothing errored. The build passed, the tests were green, the site loaded exactly as before. But somewhere in that update, the code that used to attach those headers stopped attaching them. The pages still serve; they just serve without the protections. And because a missing header produces no error and no visible difference, nobody knew the guard rails had been quietly unbolted.

This is the quiet failure: a protection that was on, then silently wasn’t, with nothing in between to tell you.

Why it stays invisible

Security headers are protections by their absence being noticed by the browser — when they’re there, the browser tightens up; when they’re gone, the browser simply does the more permissive default. Nothing breaks either way from your side. The page looks identical. No test fails, because tests check that features work, not that a header you’re no longer sending is still being sent.

The reason an update can turn them off without a word is that the header-writing often lives inside the framework, not your own code. A change in how the framework handles responses — sometimes a fix for a different bug, sometimes a security patch with an unexpected side effect — can stop the headers being written in certain cases. A Spring Security issue disclosed in March 2026 (CVE-2026-22732) worked exactly like this: a long-standing bug, surfaced by a framework update, meant that in some configurations HTTP security headers were silently no longer written to responses. Your code didn’t change, so you’d never think to look at it.

So the failure hides in the gap between “the code I wrote” and “the code I depend on” — a gap most people, reasonably, never inspect.

Find it yourself

The good news is that headers are sent with every page, so anyone on the internet can read yours — including you. This takes about a minute.

  1. Go to securityheaders.com (a free scanner built by security researcher Scott Helme).
  2. Type in your site’s address and run the scan.
  3. Read the grade and the list. It shows, header by header, what your site is sending and what it isn’t — with plain-language notes on what each one does.

The headers worth caring about first are Content-Security-Policy (limits what a page can load and helps block injected scripts), X-Content-Type-Options (stops the browser guessing file types), X-Frame-Options (stops your page being framed by another site for clickjacking — newer sites do the same job with a Content-Security-Policy frame-ancestors rule), and Strict-Transport-Security (forces secure connections).

Prefer the command line? One line shows you the raw headers:

curl -sI https://yourdomain.com

Read down the output for the header names above. If a header you know you configured isn’t there, that’s your answer.

The tell-tale sign is a site that used to grade well and now doesn’t, or a header you’re certain you set that the scan says is missing.

The fix

The fix is partly to restore the headers and partly to make their disappearance something you’d notice next time.

Put the headers back. Re-add the missing headers at the level that suits you — in your application’s configuration, or, often more robustly, at the edge: your reverse proxy, load balancer, or content delivery network can attach them to every response regardless of what the application does. Setting them at the edge has the happy side effect of surviving most framework updates, because it doesn’t depend on the framework to write them.

Read the release notes when you update. When you bump a framework or a security library, skim its release notes for anything about response headers or default behaviour changing. It’s a minute’s reading that catches exactly this class of surprise.

Make “are the headers still there” a check, not a memory. The reason this bites is that nothing watches the headers between updates. Add a lightweight check that fails your build or pings you if an expected header goes missing — even a recurring reminder to re-run the securityheaders.com scan once a month turns an invisible regression into a visible one.

None of this is a big project. It’s re-sending a few lines your site was already sending, and then arranging to be told if they ever quietly stop again — which, given how easily an update can switch them off, is the part worth keeping.

Check your inbox — confirm and you're in. Latest issue: The Remote Desktop you opened "just for now" is still open.

One real, fixable exposure every week. Free.