How every badge is scored
Every badge links to the methodology version that produced it. Changes bump the version, and old results keep their version. The canonical copy lives in the repository at docs/methodology.md.
States
- pass / warn / fail: measured.
- N/A: not applicable (for example, no TypeScript in a repo). Excluded from scoring, and the weights are renormalised.
- INSUFFICIENT DATA: applicable but not measurable (for example, CrUX has no field data). Unavailable is never treated as clean.
- error: the scan failed. The last good result is served with its timestamp.
Overall security grade
| Category | Weight |
|---|---|
| Security headers | 15 |
| TLS (validity, expiry, protocol) | 20 |
| Known vulnerabilities (OSV / Dependabot) | 25 |
| DNS & email (SPF, DMARC, DNSSEC, CAA) | 10 |
| Application security (CodeQL, secret scanning, opt-in ZAP) | 20 |
| Supply chain (SLSA provenance, pinned actions, signed releases) | 10 |
If under 50% of the total weight is measurable, the grade is INSUFFICIENT DATA. Grades: A+ ≥95, A ≥90, B ≥80, C ≥70, D ≥60, F <60.
Security headers (0–100)
HSTS with max-age ≥180 days (25), CSP without unsafe-inline (25), X-Content-Type-Options: nosniff (10), X-Frame-Options or CSP frame-ancestors (10), Referrer-Policy (10), Permissions-Policy (10), COOP (10).
TLS expiry
≥30 days: 100 · 14–29 days: 75 (warn) · under 14 days: 40 (fail) · expired: 0.
DNS
SPF 25 · DMARC reject 30 / quarantine 22 / none 8 · DNSSEC (AD bit) 25 · CAA 10 · IPv6 10.
Core Web Vitals
Field (CrUX, p75, 28-day) and lab (Lighthouse via PSI) are reported separately and never blended. Good means LCP ≤ 2.5 s, INP ≤ 200 ms and CLS ≤ 0.1. No field data means INSUFFICIENT DATA for the field badge.
Vulnerabilities
OSV severity counts (critical, high, medium, low). Score: 100 − 40·critical − 15·high − 5·medium − 1·low, floored at 0.
Freshness and caching
Badges are rendered from the latest stored result and never trigger a scan. Free projects refresh daily. Pro projects refresh hourly, with TLS every 6 hours. Pending badges cache for 5 minutes and measured badges for 1 hour at the edge.
Scanning conduct
Passive checks only, unless a domain owner has verified ownership with a DNS TXT record and opted in to active scans. See SecuremarkBot.