Hamdy Tabsissi
EN

Security Observatory In production Personal project

Noticing automatically when a site's security slips

A small robot that checks my websites every 30 minutes and flags any security setting that has quietly disappeared.

The need

A security setting removed by mistake during an update is invisible — until an audit, or a customer, notices it.

The idea

Don't rely on remembering to check. Make the check run by itself, apart from what it watches, so one outage can never hide another.

What I built

  • A checker for the standard protections a website should send: five security headers, the switch to HTTPS, cookie settings, and certificate expiry with a three-week warning.
  • It runs on its own schedule, outside the websites, and stores its history in its own database.
  • A private dashboard, behind an authentication gate.

The result

  • 30 minbetween two checks
  • 5security headers verified on every pass
  • 3 weekswarning before a certificate expires
  • 30 Aug 2026in service since

On its first pass it found a header revealing the version of the framework in use — fixed within the hour. Then it caught its own mistake: its first dashboard was public and listed in the sitemap, effectively a map for attackers. It was closed the same day and reopened behind authentication.

In pictures

Diagram: my websites, an automatic check of headers, TLS and cookies, then a history of results, continuously

What I learned

A security tool must pass its own test first. A monitoring tool that publicly shows what it monitors becomes a reconnaissance tool for anyone who finds it.

Technical details Stack, architecture and decisions — for technical readers

Stack

  • Node.js (no npm dependency)
  • Express
  • SQLite (node:sqlite)
  • systemd timer
  • Cloudflare Access

How it works

  • Checks: presence of CSP, HSTS, X-Frame-Options, X-Content-Type-Options and Referrer-Policy; no Server or X-Powered-By leak; Secure and HttpOnly on every cookie; HTTP → HTTPS redirect; TLS certificate not expiring within three weeks.
  • Zero npm dependency — Node built-in modules only.
  • Decoupled by design: the checker is a systemd service triggered every 30 minutes that writes to its own SQLite database; the dashboard only reads that database and never runs a check itself.
  • After the self-inflicted exposure: dashboard removed from the sitemap and robots.txt, service identifiers moved out of the source code, then reopened only behind Cloudflare Access on a dedicated subdomain.

Still missing

  • Dashboard not public — by design