← work / websentry
WebSentry
Website security scanning and monitoring on Cloudflare Workers
// the problem
Small teams ship sites with missing headers, weak TLS and vulnerable JS libraries, and only find out when something breaks. WebSentry grades a site in seconds and watches it for regressions.
// context
The most complete of a family of small Cloudflare Workers products built on the same edge primitives, with paid plans, monitoring and a WordPress plugin.
// what I built
- Fifteen security checks: SSL/TLS, security headers, CSP, cookies, CORS, DNS and email authentication, mixed content, SRI, information disclosure, vulnerable JS libraries, redirects and form security.
- A letter grade (A+ to F) with a shareable report URL, plus a white-label printable report.
- Scheduled monitoring: cron enqueues rescans, a queue consumer works through them, and email alerts fire when a grade drops.
- A REST API for CI/CD pipelines and a WordPress plugin.
// key decisions
- Grade only what was actually seen
When a firewall or bot challenge answers instead of the site, that category is reported as not scanned and its points leave the denominator. A 403 or 429 alone does not count; it must look like a challenge page. A complete grade is given up so the report never makes claims about headers it never saw.
- Independent check modules in one Promise.all
Each of the 15 checks fetches and scores on its own, so one failing check cannot break the others and a new check is a new file. The cost is repeated requests to the target.
- Cron enqueues, the consumer claims with a lock
The daily cron only enqueues due monitors, in chunks of 100. The consumer claims each monitor with an atomic UPDATE that sets a 30-minute lock before scanning, because cron and queue delivery can repeat and had caused double scans.
- Scan results in R2, metadata in D1
Full result JSON goes to R2 and D1 keeps the small rows, because D1 is a single-writer SQLite database and write throughput is its known bottleneck. If the R2 write fails the scan still succeeds, with reads falling back to D1.
// results
- 15 independent check modules.
- 20 D1 migrations as the product grew from launch in May 2026.