Veritsu

Reference

The nine checks, in full

Every check Veritsu runs, what it actually tests, the consequence of failing it, and the steps to fix it. All of it is verified from outside your network — no credentials, no agent, no privileged access.

Email authentication

SPF record

RFC 7208

Looks up your domain's TXT records and checks that exactly one valid SPF record exists, ending in a terminal mechanism (`-all`, `~all`) or a `redirect=`.

Why it matters. SPF tells receiving mail servers which hosts may send mail as your domain. With no record — or with two, which invalidates both under RFC 7208 — anyone can send mail that appears to come from you, and receivers have no basis to reject it.

How to fix it

  1. 1Publish a single TXT record at your root domain starting with `v=spf1`.
  2. 2List every service that sends mail as you (your mail provider, marketing tools, ticketing systems, CI alerts) using `include:` mechanisms.
  3. 3End with `-all` (hard fail — reject anything else) or `~all` (soft fail) once you're confident the list is complete.
  4. 4If you have more than one SPF record, merge them into one. Multiple records are a permanent error, not a warning.
  5. 5Keep total DNS lookups at or under 10 — `include:` chains count, and exceeding the limit invalidates the record.

TXT record at your root domain

v=spf1 include:_spf.google.com include:sendgrid.net -all

DKIM record

RFC 6376

Queries `<selector>._domainkey.<your-domain>` across twenty selectors used by common providers, and confirms a published key carries real key material.

Why it matters. DKIM cryptographically signs your outgoing mail so receivers can prove it wasn't altered in transit and genuinely came from you. Without it, DMARC has only SPF to rely on — and SPF breaks whenever mail is forwarded.

How to fix it

  1. 1Enable DKIM signing in your email provider's admin console — most generate the key pair for you.
  2. 2Publish the TXT record they give you at the selector they specify.
  3. 3Verify by sending a message to an external mailbox and checking the `Authentication-Results` header reads `dkim=pass`.
  4. 4Rotate keys periodically, and remove selectors for services you no longer use.

DMARC record

RFC 7489

Looks for a `v=DMARC1` TXT record at `_dmarc.<your-domain>`.

Why it matters. SPF and DKIM alone tell a receiver how to test your mail, but not what to do when the test fails. DMARC supplies that instruction and gives you reports on who is sending as your domain.

How to fix it

  1. 1Publish a TXT record at `_dmarc.<your-domain>` starting with `v=DMARC1`.
  2. 2Start with `p=none` plus an `rua=` reporting address — this changes nothing about delivery but starts the reports flowing.
  3. 3Read the aggregate reports for a few weeks to find every legitimate sender before tightening the policy.

TXT record at _dmarc.yourdomain.com

v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com

DMARC policy strength

RFC 7489

Reads the `p=` tag from your DMARC record and grades its strength.

Why it matters. `p=none` is monitoring only — spoofed mail still lands in inboxes. It's the correct starting point, but leaving it there indefinitely means you get the reports without any of the protection.

How to fix it

  1. 1Confirm from your DMARC aggregate reports that every legitimate sender passes SPF or DKIM.
  2. 2Move to `p=quarantine` so failing mail is junked rather than delivered.
  3. 3After a clean period at quarantine, move to `p=reject` — failing mail is refused outright.
  4. 4Consider rolling out with `pct=` (e.g. `pct=25`) to apply the policy to a fraction of mail first.

Strongest policy

v=DMARC1; p=reject; rua=mailto:dmarc-reports@yourdomain.com

SSL / TLS

Certificate validity

Opens a real TLS connection to port 443 and verifies the presented certificate chains to a trusted root and is currently within its validity window.

Why it matters. A certificate that fails to verify triggers a full-page browser interstitial. Most visitors will not click through it, and those who learn to click through are being trained to ignore exactly the warning that matters.

How to fix it

  1. 1Confirm the server sends the full chain — the leaf certificate plus any intermediates. A chain that validates in your browser can still fail elsewhere if intermediates are missing.
  2. 2Check the certificate covers the exact hostname visitors use, including the `www` variant if you serve it.
  3. 3If you use Let's Encrypt, verify the renewal timer is active and actually reloading the web server after renewal.

Certificate expiry window

Reads the certificate's expiry date and reports how many days remain — a warning at 30 days, a failure at 14.

Why it matters. Certificate expiry is the most common and most preventable cause of site outages. It fails suddenly, at a moment nobody chose, and takes the whole site down for every visitor at once.

How to fix it

  1. 1Automate renewal — Certbot, your host's built-in ACME client, or your CDN's managed certificates.
  2. 2Verify the automation reloads the web server; a renewed certificate on disk that was never loaded still serves the old one.
  3. 3Keep an independent expiry alert so a silently broken renewal job is caught before the deadline rather than after.

TLS protocol version

RFC 8996

Records the protocol version negotiated normally, then opens a second connection offering only TLS 1.0/1.1 to see whether the server still accepts them.

Why it matters. TLS 1.0 and 1.1 are formally deprecated (RFC 8996) and carry known weaknesses. Accepting them keeps you exposed to downgrade attacks and fails most compliance baselines — even when modern clients negotiate something better.

How to fix it

  1. 1Set your server's minimum protocol version to TLS 1.2, and prefer TLS 1.3.
  2. 2On nginx: `ssl_protocols TLSv1.2 TLSv1.3;`. On Apache: `SSLProtocol -all +TLSv1.2 +TLSv1.3`.
  3. 3Behind a CDN or load balancer, change it there — that's what terminates TLS, and the origin's own setting won't be what visitors reach.

Web hardening

Security headers

Fetches your homepage over HTTPS and checks for four response headers: Strict-Transport-Security, Content-Security-Policy, X-Frame-Options (or CSP `frame-ancestors`), and X-Content-Type-Options.

Why it matters. These headers turn on browser protections that are off by default. Without them the browser will happily downgrade to HTTP, run injected scripts, let your pages be framed for clickjacking, and guess at content types.

How to fix it

  1. 1HSTS — `Strict-Transport-Security: max-age=31536000; includeSubDomains`. Forces HTTPS for future visits. Start with a short max-age while you confirm every subdomain serves HTTPS.
  2. 2CSP — start in report-only mode (`Content-Security-Policy-Report-Only`) to find what would break, then enforce. This is the highest-effort and highest-value header.
  3. 3Frame protection — `X-Frame-Options: DENY`, or better, CSP `frame-ancestors 'none'`, which supersedes it.
  4. 4MIME sniffing — `X-Content-Type-Options: nosniff`. A one-line change with essentially no risk of breakage.

A reasonable starting set

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'

security.txt

RFC 9116

Fetches `/.well-known/security.txt` and validates it as an RFC 9116 file — it must be plain text, carry a `Contact:` field, and have an `Expires:` date in the future.

Why it matters. When a researcher finds a vulnerability in your systems, this file is how they know where to report it. Without one, reports go to a sales address, a support queue, or a public tweet — or nowhere at all.

How to fix it

  1. 1Create a plain-text file served at `https://yourdomain.com/.well-known/security.txt`.
  2. 2Include at minimum a `Contact:` line (a mailto: or a reporting form URL) and an `Expires:` date, both required by the RFC.
  3. 3Set `Expires:` no more than about a year out and diary a reminder to refresh it — an expired file signals an unmaintained process.
  4. 4Make sure the path returns the file itself, not your app's HTML catch-all route.

/.well-known/security.txt

Contact: mailto:security@yourdomain.com
Expires: 2027-01-01T00:00:00.000Z
Preferred-Languages: en
Canonical: https://yourdomain.com/.well-known/security.txt

Check your own domain

Results come back with these same fix steps attached to whatever fails.

Nine checks in about ten seconds. No signup, nothing installed.

Questions about method or privacy? Read the FAQ →