Owl Keeper

Features / Response security

Security header monitoring

Anything can print the headers a site sends back. The useful question is which are missing, which are set to a value that does nothing, and which single one of those is a hole rather than a hardening job — and whether any of it changed since the last deploy.

Why a list of headers is not an answer

Run any header scanner and you get a wall of red. Nine things are missing, each one presented with the same urgency, and the reasonable response after the second visit is to stop looking. Meanwhile the finding that actually matters — a session cookie being served without the Secure flag — sits in the middle of the list wearing the same colour as an absent Permissions-Policy.

The grading here exists to separate those. There is one class of finding treated as a genuine problem. Everything else is hardening: worth doing, not worth waking anybody, and reported in amber so that the day something goes red you believe it.

The one that is a hole

A cookie set without Secure. That cookie travels in clear text the first time somebody types the address without https://, on whatever network they happen to be on. If it is a session cookie, that is the session, and no amount of TLS elsewhere on the site helps.

Cookies are also checked for HttpOnly and SameSite, but those are reported as warnings and named individually, because the judgement depends on which cookie it is. Every framework ships a CSRF cookie the page is deliberately allowed to read; a session cookie readable by scripts is a different matter. Naming them lets somebody who knows which is which decide in a glance, rather than being told "a cookie is readable" and having to go and look.

HSTS, with a number that means something

Present is not the same as effective. Strict-Transport-Security is checked for its max-age, and a value under roughly six months is reported rather than ticked off — a browser forgets it sooner than most people renew anything, and the preload list refuses it outright. A site with max-age=300 has an HSTS header and, for practical purposes, no HSTS.

Whether plain HTTP answers at all is checked alongside it. A redirect to HTTPS is fine and is recorded as fine. Port 80 refusing the connection outright is stronger, and the difference is reported rather than flattened into a tick.

The rest of the grade

Checked Reported as
Content-Security-Policy Present, or missing — the main defence against injected scripts
Frame protection Satisfied by X-Frame-Options or a CSP frame-ancestors; either will do, and only one of them is the old way
X-Content-Type-Options Whether browsers are told not to guess that an upload is a script
Referrer-Policy Whether full URLs leak to every site you link to
Permissions-Policy Whether camera, microphone and location access are constrained
Server, X-Powered-By Whether they carry version numbers, which is free reconnaissance for anyone scanning for a known bug in exactly that release

The part a one-off scan cannot do

A header that disappears is an event. A Content-Security-Policy that was there last week and is not there today gets written into the site's history with the date it went — because that is a deploy nobody meant to make, and it is invisible to everything else you have.

This is the real difference between checking headers and monitoring them. A scan tells you the state of a site at the moment you ran it, which is useful once. A site that is checked every day tells you when the state changed, which is what you actually need when a framework upgrade quietly drops a middleware, or a new CDN configuration strips a header on the way through, or somebody adds a subdomain that never got the config the main site has.

Only differences are recorded. A check that finds exactly what it found yesterday writes nothing at all, so the history is a short list of things that moved rather than a year of identical rows.

For people looking after other people's sites

Every site added is graded the same way, and the findings sit on the same page as its certificate, its registration and its mail records. That makes two questions answerable that are otherwise a morning's work each: which of our sites is missing a CSP, and what changed on this client's site since the handover.

None of this reaches a client status page. Those show uptime, what is answering, and when the certificate and registration renew — never monitor names, never addresses, and nothing from the security findings.

Questions

Is this a penetration test?

No, and it should not be sold to a client as one. This reads what the server sends back on a normal request to the homepage and grades it. It does not probe for vulnerabilities, attempt any input, or authenticate. It is the check that tells you the front door has a lock on it, not the one that tries to pick it.

Does a missing header mean the site is insecure?

Usually not. Most of these are defence in depth, and a well-built application with none of them is safer than a badly built one with all of them. That is precisely why they are graded rather than counted: a score out of nine invites you to chase the number, and the number is not the point.

What about pages other than the homepage?

The grade is taken from the site's homepage response. Headers are almost always set globally — at the framework, the web server or the CDN — so the homepage is a reliable read on the whole site. A path with deliberately different headers is not something this will notice.

Will it tell me how to fix something?

The finding names the header and what its absence permits. It does not generate config, because the correct Content-Security-Policy for a site depends entirely on what that site loads, and a policy pasted from a monitoring tool is either so loose it does nothing or so tight it breaks the checkout.

How often is it checked?

Daily, on every plan, for every site. The check interval on the paid plans buys faster uptime checks; the daily passes over certificates, domains, mail and response security run the same for everybody.