Every check in your SecureMonk scan, mapped to the attack it stops
Published May 27, 2026. About a ten-minute read.
When you run a SecureMonk scan, you get a score and a list of findings. The findings are useful as a to-do list, but they do not always explain why each one matters. This guide walks every TLS and header check we run, names the attack category each finding is connected to, and gives you the one-line fix when there is one.
We deliberately keep this guide focused on TLS and headers. Those are the two areas where every site can be measured against a clear baseline and the fixes are straightforward. The optional vulnerability scan is a different animal. It depends on detecting versions of software you may not even know you are running, and on cross-referencing those versions against advisory databases. The score on the homepage is TLS plus headers only for the same reason. They are the deterministic part.
TLS findings
Certificate not trusted by public CAs
What we detect. The server presents a certificate signed by a CA your operating system or browser does not trust by default. Self-signed, signed by an internal CA, or signed by a CA that has been removed from the public trust stores for a known reason.
What it lets an attacker do. Anyone on the network path between the visitor and the server can present their own certificate and intercept the connection. Browsers warn the user, but a non-trivial fraction of users click through warnings. On API clients and IoT devices, certificate validation is sometimes disabled entirely as a workaround, which effectively turns the connection back into plaintext.
Fix.For a public site, use Let’s Encrypt or any other free public CA. The setup is automatable in under an hour. For an internal-only service, install your private CA’s root certificate on every client device.
Certificate expired
What we detect.The certificate’s validity end-date is in the past.
What it lets an attacker do.Mostly, this breaks the site for every visitor on every modern browser. Browsers refuse expired certificates and refuse to let users click through. The “attack” enabled is denial of service against your own users by your own infrastructure.
Fix.Automate certificate renewal. Most modern hosting platforms (Let’s Encrypt with certbot, Caddy, Cloudflare) do this automatically. If you are still renewing certificates by hand, switch.
No modern TLS (TLS 1.2 or 1.3) supported
What we detect. The server only accepts connections over TLS 1.0, TLS 1.1, or SSL 3.0.
What it lets an attacker do. Use any of the documented protocol-level attacks against legacy TLS: BEAST (CBC weakness in TLS 1.0), POODLE (SSL 3.0 padding oracle), and a long list of cipher-specific weaknesses that TLS 1.2 partially fixed and TLS 1.3 fixed entirely.
Fix. Enable TLS 1.2 and TLS 1.3 in your server config. Almost every modern web server defaults to these. The fix is usually removing the explicit configuration that disabled them.
Legacy TLS protocols (1.0, 1.1) still accepted
What we detect. The server accepts TLS 1.2 or 1.3 (good) but also accepts 1.0 or 1.1 (deprecated).
What it lets an attacker do. Downgrade attacks. An attacker who can interfere with the connection can force the negotiation down to a weaker protocol if both sides support it. From there, the legacy-protocol attacks above become available.
Fix. Disable TLS 1.0 and 1.1 in your server config. For nginx: ssl_protocols TLSv1.2 TLSv1.3;.
Weak cipher suites enabled
What we detect. The server accepts cipher suites containing CBC, RC4, 3DES, DES, EXPORT, or NULL.
What it lets an attacker do. CBC implementations in TLS 1.0/1.1 are vulnerable to BEAST and padding-oracle attacks. RC4 has known biases that allow plaintext recovery. 3DES is vulnerable to SWEET32 over long-lived connections. EXPORT and NULL ciphers are intentionally weak or non-encrypted.
Fix.Use a Mozilla SSL Configurator “intermediate” profile or stricter. The generator at ssl-config.mozilla.org produces a copy-paste config for every common web server.
No forward secrecy
What we detect. Cipher suites are negotiated with non-ephemeral key exchange (plain RSA key exchange instead of ECDHE).
What it lets an attacker do.An attacker who records the encrypted traffic today and steals your server’s private key later (via breach, subpoena, or compromise) can decrypt every recorded session in retrospect.
Fix. Restrict the cipher list to ECDHE key exchange only. With TLS 1.3 enabled, you get this automatically. With TLS 1.2, set the cipher list to start with ECDHE-RSA or ECDHE-ECDSA suites.
OCSP stapling not enabled
What we detect. The server does not include the OCSP (Online Certificate Status Protocol) response in its TLS handshake.
What it lets an attacker do.Not a direct attack, but two related risks. First, the client has to fetch revocation status separately, which adds latency and exposes the visitor’s IP to the certificate authority. Second, if the OCSP responder is down, browsers fail open and accept the certificate without checking, which means a revoked certificate can still be used for some window.
Fix. Enable OCSP stapling. nginx: ssl_stapling on; ssl_stapling_verify on;. Apache: SSLUseStapling on.
Self-signed or test certificate
What we detect.Same as “certificate not trusted” but specifically flagged when the certificate’s issuer matches its subject (self-signed) or contains common test-CA strings.
What it lets an attacker do.Trains your users to click through certificate warnings. Once that is muscle memory, they will click through a real attacker’s certificate too.
Fix.Get a real certificate from Let’s Encrypt. For internal or staging environments, set up an internal CA and distribute its root certificate to clients.
Header findings
Strict-Transport-Security missing
What we detect. The server does not send the HSTS header on HTTPS responses.
What it lets an attacker do. A network-layer attacker can intercept the first request from a new visitor (which might go out as HTTP) and serve a fake plaintext page, then either keep them on HTTP or feed them through a man-in-the-middle proxy.
Fix. Add Strict-Transport-Security: max-age=31536000; includeSubDomains to every HTTPS response. See our HSTS guide for the preload discussion.
Content-Security-Policy missing
What we detect. The server does not send a CSP header.
What it lets an attacker do. A long list of injection attacks. Cross-site scripting (XSS) becomes much harder to mitigate without CSP. A compromised third-party script (an analytics provider, a chat widget) can exfiltrate data from your page. Inline event handlers in user-controlled content can execute arbitrary code. Clickjacking is open by default unless X-Frame-Options is set.
Fix. Deploy CSP, starting in report-only mode. See our CSP guide for the full path.
X-Frame-Options missing
What we detect.The server does not send X-Frame-Options or CSP’s frame-ancestors directive.
What it lets an attacker do.Clickjacking. Your page can be loaded inside a hidden iframe on an attacker-controlled page, where they can trick users into clicking your “Confirm” button while looking at their “Free iPhone” UI.
Fix. X-Frame-Options: DENY if your site does not need to be embedded. SAMEORIGINif same-origin iframes are used internally. For finer control, use CSP’s frame-ancestors directive.
X-Content-Type-Options missing
What we detect. The server does not send X-Content-Type-Options: nosniff.
What it lets an attacker do.MIME-sniffing attacks. A file uploaded by a user as a “text comment” but containing actual JavaScript can be interpreted as JavaScript by browsers that do content sniffing. With this header set, the browser refuses to override the Content-Type your server declared.
Fix. X-Content-Type-Options: nosniff. The only valid value. The only configuration option. The single easiest header in the entire list.
Referrer-Policy missing or weak
What we detect. The server does not send Referrer-Policy, or it sends unsafe-url or no-referrer-when-downgrade (the historical default).
What it lets an attacker do. Information leakage. The full URL the user came from is sent to every external resource your page loads. If your URL contains a session token, password reset key, or other sensitive query parameter, you leak it to every CDN, ad network, and analytics provider on the page.
Fix. Referrer-Policy: strict-origin-when-cross-origin is a reasonable default for most sites. no-referrer is stricter if your site does not need referrer information at all.
Permissions-Policy missing
What we detect. The server does not send a Permissions-Policy (or its predecessor, Feature-Policy).
What it lets an attacker do. XSS payloads, malicious iframes, or compromised third-party scripts can access powerful browser features your page does not actually need: geolocation, microphone, camera, USB devices, payment APIs. Without Permissions-Policy, the browser allows many of these features by default in same-origin scripts and allows several in iframes.
Fix. Disable everything your site does not use. Example: Permissions-Policy: geolocation=(), microphone=(), camera=(), usb=(), payment=(). Each entry with () means no origin is allowed to use this feature on this page.
Cross-Origin-Opener-Policy missing
What we detect. The server does not send COOP.
What it lets an attacker do. Cross-origin window references and Spectre-style side-channel attacks. An attacker page that has a reference to your window object (via window.open or target=_blank without rel=noopener) can interact with it in ways that leak information across origins.
Fix. Cross-Origin-Opener-Policy: same-origin for most sites. This isolates the browsing context so cross-origin pages cannot script your window.
Cross-Origin-Embedder-Policy missing
What we detect. The server does not send COEP.
What it lets an attacker do. On its own, mostly nothing. Its main role is to unlock high-resolution timers and SharedArrayBuffer, both of which browsers block as a Spectre mitigation unless COEP and COOP are in place. If your site does not use SharedArrayBuffer or performance.now() at high precision, COEP is a recommendation, not a requirement.
Fix. Cross-Origin-Embedder-Policy: require-corp if you need the precision-timer or SharedArrayBuffer features. Otherwise, this is informational.
Cross-Origin-Resource-Policy missing
What we detect. The server does not send CORP on resources.
What it lets an attacker do. Other origins can load your resources via <img>, <script>, and similar tags without going through CORS, which means certain side-channel timing attacks across origins are possible. The threat model is similar to COOP and COEP: real but specific to side-channel work.
Fix. Cross-Origin-Resource-Policy: same-origin on resources you do not want other origins to embed.
A note on the vulnerability scan
The optional vulnerability scan does two things: it fingerprints the technologies running on the target (Apache, nginx, WordPress, PHP, jQuery, Next.js, and so on) and cross-references the detected versions against NVD and OSV.dev. It is useful when it finds something, but it is bounded by what is fingerprintable. Modern frameworks like Next.js do not advertise their version. CDNs strip the Server header. Minified JavaScript bundles do not include version strings. Most of the time, the vuln scan can identify the technology but not the version, and a CVE lookup needs the version.
That is why TLS and headers carry all the weight in the scan score. They are deterministic, the gaps are real, and the fixes work. The vuln scan is a useful supplement when versions are detectable, not a substitute.
What to fix first
If you are starting from a low score, the priorities are nearly always the same:
- HSTS. One line, no side effects, closes a real attack window.
- X-Content-Type-Options. One line, no side effects, no maintenance.
- X-Frame-Options. One line, very few side effects. Pick DENY or SAMEORIGIN.
- Disable TLS 1.0 and 1.1. One line, almost no users affected in 2026.
- Modern cipher list. Drop CBC suites and any non-ECDHE key exchange.
- CSP. Start in report-only, iterate for a week or two, then enforce.
- OCSP stapling. Two lines. Almost free.
- Permissions-Policy. Lock down browser features your site does not need.
- Referrer-Policy. One line. Stop leaking URLs to third parties.
- The Cross-Origin family. Only if you use SharedArrayBuffer or precision timers.
Re-run the scan after each change. The score moves the moment the header arrives. The peace of mind is permanent.