Skip to main content
Docs menu Security monitoring

Security-posture scans

How CompleteStatus grades your site's security headers and TLS certificate A+ to F, how to read findings, and how to fix them with copy-paste snippets.

Last updated 6 min read

On this page

CompleteStatus's security layer continuously scans your sites and turns the results into a letter grade, A+ through F. Two monitor types produce grades:

  • Security headers — fetches the page and grades its HTTP response headers.
  • SSL/TLS certificate — inspects the certificate and the negotiated TLS connection.

Both are included on every plan, including Free.

Setting up a security scan

  1. Go to /monitors/create and pick the Security headers type (or SSL Certificate for TLS).
  2. Enter the URL to scan (the full https:// URL for headers; the bare hostname for certificates).
  3. Tick the ownership attestation — you may only scan sites you own or are authorized to check.
  4. Save. The headers scan runs on your chosen interval (daily is typical; the whole-site quick-add at /monitors/site creates it with a daily interval by default).

The onboarding wizard and the whole-site quick-add can create both monitors for you in one click.

How the header grade is calculated

Every scan starts at a score of 100 and subtracts points for each finding, by severity: critical −25, high −15, medium −10, low −5, info −2. The score maps to a grade:

Score Grade
100 A+
90–99 A
80–89 B
70–79 C
60–69 D
below 60 F

An A+ therefore requires a fully hardened header set — even an informational finding like version disclosure or a missing Cross-Origin-Embedder-Policy costs the top grade. Each check below produces at most one finding per scan (several weak cookies are one finding, deducted once).

What the headers scan checks

  • Content-Security-Policy — missing is high. A weak policy is medium: it lets inline script run ('unsafe-inline' without a nonce, hash or 'strict-dynamic'), allows 'unsafe-eval', loads scripts from a wildcard * or a scheme-only source (https:, http:, ftp:, data:), or defines neither default-src nor script-src. If the only weakness is 'unsafe-inline' in style-src, it is low. When a site sends more than one CSP, a weakness only counts if every policy has it, because browsers enforce all of them.
  • Strict-Transport-Security (HSTS) — missing, or max-age=0 (which switches HSTS off), is high. It is low when max-age is missing or under 180 days, when includeSubDomains is missing, or when the header declares preload but is not preload-eligible (preload needs max-age of at least one year, 31536000, plus includeSubDomains).
  • X-Content-Type-Options — anything other than nosniff is medium.
  • Clickjacking protection — neither X-Frame-Options nor a CSP frame-ancestors directive: high.
  • Referrer-Policy — missing is low; unsafe-url is medium.
  • Permissions-Policy — missing is low.
  • Cross-Origin-Opener-Policy / Cross-Origin-Resource-Policy — each missing header is low.
  • Cross-Origin-Embedder-Policy — missing is info. Any value clears it, including unsafe-none, so if require-corp or credentialless would break embedded third-party content, send Cross-Origin-Embedder-Policy: unsafe-none.
  • Cookie flags — cookies set without Secure, HttpOnly or SameSite are medium; a cookie with SameSite=None but no Secure makes the finding high (browsers reject it). Well-known CSRF cookies that JavaScript has to read (XSRF-TOKEN, csrftoken, _csrf, csrf_token, _xsrf, also behind a __Host-/__Secure- prefix) are not asked for HttpOnly.
  • Cookie name prefixes — a __Host- cookie without Secure, without Path=/ or with a Domain attribute, or a __Secure- cookie without Secure, is info.
  • CORS — Access-Control-Allow-Origin: * combined with Access-Control-Allow-Credentials: true is info: browsers refuse that combination, so it has no effect. List the specific trusted origins if cross-origin requests need cookies.
  • Version disclosure — info. Flagged when the Server header contains a version number, or when any of these headers is present: X-Powered-By, X-AspNet-Version, X-AspNetMvc-Version, X-Powered-CMS, X-Generator, X-Drupal-Cache, X-Drupal-Dynamic-Cache, X-Runtime.

How the TLS certificate grade is calculated

The certificate check uses the same 100-point scale, but some problems are hard failures that force an F regardless of score: an expired certificate, a protocol below TLS 1.2, an RSA key under 2048 bits (EC under 256), or a SHA-1/MD5 signature. Deductions on top of that:

  • Invalid trust chain: −40 (high)
  • Expires in under 7 days: −30 (high); under 14 days: −15 (medium); under 30 days: −5 (low)
  • Hostname not covered by the certificate's SANs/CN: −20 (medium)
  • Negotiated TLS 1.2 instead of 1.3: −5 (low)

A certificate check passes only while the chain is valid, the certificate is unexpired, and the grade is C or better.

Reading your results

On the monitor page

Open a headers monitor from /monitors and the Security headers panel shows the grade badge, every finding sorted critical → info, whether each header is Present or Missing, its current value, and the raw response headers CompleteStatus observed.

The security overview

The /security page aggregates all your certificate and headers monitors in one place:

  • Grade distribution — how many monitors sit at each grade.
  • Average score and worst grade across the fleet.
  • 30-day score trend — a chart of your daily average security score.
  • Findings inbox — every open finding across all monitors, sorted by severity and filterable by severity (critical, high, medium, low, info) and by project.

Fixing findings with copy-paste snippets

Every failing header finding ships ready-to-use remediation for four platforms. On the monitor page, expand a finding and use the Fix — copy & paste tabs:

  1. Pick your platform: nginx, Apache, Caddy or PHP.
  2. Click the copy button next to the snippet.
  3. Paste it into your server config (nginx server block, Apache vhost/.htaccess with mod_headers, Caddyfile, or PHP header() call) and reload.
  4. Click Check now on the monitor to re-scan immediately instead of waiting for the next interval.

For example, the HSTS fix for nginx is:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

Warning: Test CSP changes carefully. The suggested strict policy (default-src 'self'; script-src 'self'; …) will block inline scripts and third-party assets your site may rely on. Adapt the allowlist before deploying to production — How to fix your Content-Security-Policy walks through a safe report-only rollout.

Alerts on grade drops

A headers monitor passes only while its grade is B or better. If a deploy or config change drops the grade to C, D or F, the check starts failing; after two consecutive failed checks CompleteStatus opens an incident and notifies every alert channel whose rule includes the down event. When the grade recovers to B or better, the incident resolves and up (recovery) alerts go out.

To wire this up, open the monitor, add an alert rule pointing at a channel, and select the events you want (the rule form also offers grade_drop and cert_expiry event options alongside down, up and anomaly). See Getting started for channel setup.

Note: Grade regressions surface through the normal incident flow — you'll see the exact grade and every new finding in the incident's monitor detail.

Scanning many domains at once

On the Business and Agency plans, the bulk security audit at /audits scans a whole list of domains (up to 50 per scan on Business, 500 on Agency) across four areas — headers, TLS, email authentication and reputation — and produces an overall grade per domain, with CSV export and white-label PDF reports. It's a point-in-time audit tool, separate from continuous monitors.

Ready to try it?

10 monitors, security grading and email-authentication checks on the free tier — commercial use allowed.