TLS findings: what each one means and how to fix it
Every finding a TLS check can report, with what it means, how to fix it, and which baselines count it. Availability findings set the check's status whatever you selected; configuration findings count against the baselines you selected, and are recorded and graded otherwise. The result drawer links each finding to its entry here.
Availability
Findings about whether real clients can connect. They set the status on every check.
Certificate expired expired
The certificate, or one in its chain, is past its end date, and every client refuses the connection. Renew it and deploy the new certificate with its intermediates; if renewal is automated, check why it stopped.
Sets the status to error.
Certificate expires inside the error window expiry_error
A certificate in the chain expires inside your error window. Renew it now: at this point automated renewal has already failed at least once.
Sets the status to error.
Certificate expires inside the warning window expiry_warning
A certificate in the chain expires inside your warning window. Automated renewal normally happens earlier, so check that it is still running.
Sets the status to warning.
Certificate not yet valid not_yet_valid
The certificate starts in the future. Either it was deployed too early or the issuing system clock is wrong; deploy a certificate that is valid now.
Sets the status to error.
Chain not trusted untrusted
The chain does not lead to a trusted root. Most often the server leaves out its intermediate certificate: configure the full chain the CA provided. In nginx, ssl_certificate takes the certificate followed by the intermediates.
Sets the status to error.
Name not covered by the certificate hostname_mismatch
No name in the certificate covers the host the check connects to. Issue the certificate for that name, or set the check’s server name to the name the certificate is for.
Sets the status to error.
Certificate revoked revoked
The CA has revoked the certificate, and clients that check revocation refuse it. Issue and deploy a new one; find out why it was revoked, since that usually means the key was exposed.
Sets the status to error.
Certificate Transparency proofs missing ct_non_compliant
The certificate lacks the Certificate Transparency proofs browsers require. Get it reissued by the CA; publicly trusted CAs add the proofs as standard.
Sets the status to error.
No key matches the pins pin_mismatch
No key on the served chain matches the pins you set. Either the certificate was renewed with a new key, which breaks the mobile apps that pin it, or the pins on the check are out of date. Keep a backup pin for the next key.
Sets the status to error.
CAA records exclude the issuing CA caa_forbids_issuer
The name’s CAA records do not allow the CA that issued the current certificate, so its renewal will be refused. Add that CA to the records, or change CA before renewing.
Sets the status to warning.
Handshake refused handshake_refused
The server refuses what current clients offer, or the port does not speak TLS at all. Check the port and the server’s TLS settings; the result says what the server answered.
Sets the status to error.
Only legacy key exchange legacy_kex_only
The server completes a handshake only with legacy key exchange, which many current clients no longer offer. Enable ECDHE cipher suites.
Sets the status to warning.
TLS 1.1 or older negotiated legacy_protocol
The server negotiates TLS 1.1 or older, which current browsers refuse. Enable TLS 1.2 and 1.3.
Sets the status to error.
Private or reserved address blocked_target
The host resolves to a private or reserved address, which checks do not connect to. Check the host name, or monitor the service from inside your own network.
Sets the status to error.
No TLS reply unreachable
Three attempts got no TLS reply. The result is unknown and judges nothing; whether the server is up is an HTTP or ping check’s job.
Makes the result unknown.
Protocol versions
SSL 3 accepted accepts_ssl3
The server still answers SSL 3, which is broken. Turn it off. In nginx: ssl_protocols TLSv1.2 TLSv1.3; In Apache: SSLProtocol -all +TLSv1.2 +TLSv1.3.
Required by: Mozilla (tls_versions), BSI (§3.2), NIST (§3.1), NCSC-NL (Table 1: Insufficient).
TLS 1.0 accepted accepts_tls10
The server still answers TLS 1.0, which current browsers no longer use. Turn it off, as for SSL 3.
Required by: Mozilla (tls_versions), BSI (§3.2), NIST (§3.1), NCSC-NL (Table 1: Insufficient).
TLS 1.1 accepted accepts_tls11
The server still answers TLS 1.1, which current browsers no longer use. Turn it off, as for SSL 3.
Required by: Mozilla (tls_versions), BSI (§3.2), NIST (§3.1 (should not)), NCSC-NL (Table 1: Insufficient).
TLS 1.2 accepted past its date accepts_tls12
The server accepts TLS 1.2 past the date the baseline allows it. Plan to serve TLS 1.3 only once your clients allow it.
Required by: BSI (§3.2 Table 2 (TLS 1.2 up to 2031)).
No TLS 1.3 no_tls13
The server does not negotiate TLS 1.3. Enable it; it is faster and drops everything weak by design. Any current server software supports it.
Required by: NIST (§3.1).
Intolerant of newer TLS versions version_intolerant
The server aborts a handshake that offers a newer TLS version than its own instead of negotiating down. This breaks clients as versions move on; update the server software or the device in front of it.
Required by: NIST (§3.1).
Cipher suites
Null ciphers accepted accepts_null
The server accepts cipher suites that encrypt nothing. Remove them from the server’s cipher list.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NIST (§3.3.1), NCSC-NL (Tables 6, 8: Insufficient).
Anonymous key exchange accepted accepts_anon
The server accepts anonymous key exchange, which anyone in the path can intercept. Remove those suites.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NIST (§3.3.1), NCSC-NL (Table 2: Insufficient).
Export-grade ciphers accepted accepts_export
The server accepts export-grade suites, which are broken. Remove them.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NIST (§3.3.1), NCSC-NL (Table 2: Insufficient).
RC4 accepted accepts_rc4
The server accepts RC4, which is broken. Remove it from the cipher list.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NIST (§3.3.1), NCSC-NL (Table 8: Insufficient).
DES or 3DES accepted accepts_3des
The server accepts DES or 3DES, which are too weak. Remove them from the cipher list.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NIST (§3.3.1.1), NCSC-NL (Table 8: Insufficient).
Key exchange without forward secrecy accepts_static_kex
The server accepts key exchange without forward secrecy, so a key stolen later decrypts past traffic. Offer only ECDHE (and TLS 1.3) suites.
Required by: Mozilla (ciphers), BSI (RSA key transport, not in Tables 3–5; §3.3.1.2 Table 4 (up to 2026)), NCSC-NL (Table 6: Insufficient).
CBC suites with SHA-1 MAC accepted accepts_sha1_mac
The server accepts CBC suites with SHA-1 message authentication. Prefer AES-GCM and ChaCha20 suites and remove these.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NCSC-NL (Table 9: Insufficient).
CBC suites accepted accepts_cbc
The server accepts CBC suites, which have a long record of padding attacks. Offer AEAD suites (AES-GCM, ChaCha20) only.
Required by: Mozilla (ciphers), NCSC-NL (Table 8: To be phased out).
Finite-field DHE suites accepted accepts_dhe
The server accepts finite-field DHE suites, which are slow and being retired. Offer ECDHE suites instead.
Required by: Mozilla (ciphers), BSI (§3.3.1.1 Table 3 (TLS 1.2 DHE up to 2029)), NCSC-NL (Table 6: To be phased out).
TLS 1.2 suites outside the baseline suite_not_allowed
The server accepts TLS 1.2 suites the baseline does not list, such as ChaCha20, CCM, Camellia or ARIA, depending on the baseline. The finding names them; remove them if the baseline matters to you.
Required by: Mozilla (ciphers), BSI (not in Tables 3–5), NIST (§3.3.1.1), NCSC-NL (Table 8: Insufficient).
TLS 1.3 suites outside the baseline tls13_suite_not_allowed
The server accepts TLS 1.3 suites the baseline does not list. For BSI and NIST that is ChaCha20; for Mozilla and NCSC-NL the CCM suites. In OpenSSL-based servers TLS 1.3 suites are set separately, for example ssl_conf_command Ciphersuites in nginx.
Required by: Mozilla (ciphersuites), BSI (§3.4.4 Table 13), NIST (§3.3.1.2), NCSC-NL (Table 8: Insufficient).
Key exchange
Key exchange groups outside the baseline kex_group_not_allowed
The server accepts key exchange groups the baseline does not list, for example X25519 under BSI or NIST. Set the groups explicitly: ssl_ecdh_curve in nginx, SSLOpenSSLConfCmd Curves in Apache.
Required by: Mozilla (tls_curves), BSI (§3.3.2 Table 6, §3.4.2 Table 10), NIST (§3.3.1, §3.4.2.2), NCSC-NL (Tables 3, 6, 7: Insufficient).
Required key exchange group missing no_required_kex_group
The server negotiates none of the groups the baseline requires, P-256 or P-384 for NIST. Add one of them to the server’s groups.
Required by: BSI (§3.3.2 Table 6, §3.4.2 Table 10), NIST (§3.4.2.2).
No post-quantum hybrid key exchange no_pq_hybrid
The server negotiates no post-quantum hybrid key exchange, which the baseline expects from its date. Current OpenSSL and BoringSSL versions offer one.
Required by: BSI (§3.1.3 (classical key agreement alone up to 2031)).
Weak DH group weak_dh
The server’s finite-field DH group is smaller than the baseline allows, or is not one of the standard RFC 7919 groups. Use a standard group of at least the size named, or drop DHE.
Required by: Mozilla (dh_param_size), BSI (§3.6.1 Table 14), NIST (§3.3.1, §3.3.3), NCSC-NL (Table 7: Insufficient).
Handshake
TLS compression enabled tls_compression
The server accepts TLS-level compression, which leaks secrets (CRIME). Turn it off.
Required by: BSI (§3.3.4.3), NIST (§3.7), NCSC-NL (Table 10: Insufficient).
No secure renegotiation insecure_renegotiation
The server does not support secure renegotiation (RFC 5746). Update the TLS library; every maintained one supports it.
Required by: BSI (§3.3.4.1), NIST (§3.4.1.1), NCSC-NL (Table 11: Insufficient).
Heartbeat extension enabled heartbeat_enabled
The server negotiates the Heartbeat extension, the one Heartbleed abused. It is only reported, never exercised; turn it off.
Required by: BSI (§3.3.4.6).
Truncated HMAC enabled truncated_hmac
The server negotiates truncated HMAC, which weakens integrity. Turn it off.
Required by: BSI (§3.3.4.2), NIST (§3.4.2 item 8).
No Extended Master Secret no_extended_master_secret
The server does not negotiate Extended Master Secret (RFC 7627). Update the TLS library or enable it.
Required by: BSI (§3.3.4.7), NIST (§3.4.1.3).
CBC without Encrypt-then-MAC cbc_without_etm
The server uses CBC suites without Encrypt-then-MAC (RFC 7366). Enable it, or better, drop the CBC suites.
Required by: BSI (§3.3.4.5), NIST (§3.4.2.7).
Downgrade not prevented (TLS_FALLBACK_SCSV) no_fallback_scsv
The server accepts a downgraded handshake despite TLS_FALLBACK_SCSV, so an attacker can push clients to an older version. Update the TLS library, or turn off the older versions.
Required by: NIST (§3.4.2.1).
Handshake signed with RSA PKCS #1 v1.5 pkcs1_handshake_signature
Offered only RSA PKCS #1 v1.5 signatures, the server signs its key exchange with one. Some baselines want RSA-PSS; current libraries prefer it when clients offer it.
Required by: BSI (§3.3.3 Table 7 (rsa up to 2025)).
Handshake signed with SHA-1 weak_handshake_hash
Offered only SHA-1, the server signs its key exchange with it. Restrict the signature algorithms to SHA-256 or stronger.
Required by: BSI (§3.3.3 Table 8), NIST (§3.3.3), NCSC-NL (Table 9: Insufficient).
Certificate
Certificate key too small weak_key
The certificate’s key is smaller than the baseline allows. Issue the next certificate with a larger key, or an ECDSA one.
Required by: Mozilla (certificate_curves; rsa_key_size), BSI (§3.6.1 Table 14), NIST (§3.2.1 Table 3-1, §3.3.3), NCSC-NL (Table 3: Insufficient; Table 4: Insufficient).
Intermediate key too small weak_chain_key
An intermediate certificate’s key is smaller than the baseline allows. The intermediate comes from your CA; ask for a chain with a stronger one, or change CA.
Required by: BSI (§3.6), NIST (§3.3.3).
MD5 or SHA-1 signature in the chain weak_signature
A certificate in the chain is signed with MD5 or SHA-1. Get it reissued; if it is the intermediate, your CA has a current one.
Required by: Mozilla (certificate_signatures), BSI (§3.3.3 Table 8, §3.4.3 Table 12), NIST (§3.3.3), NCSC-NL (Table 9: Insufficient).
RSA PKCS #1 v1.5 signature in the chain pkcs1_signature
A certificate in the chain is signed with RSA PKCS #1 v1.5, which some baselines no longer recommend. Meeting them in practice means an ECDSA chain.
Required by: BSI (§3.3.3 Table 7, §3.4.3 Table 12 (up to 2025)).
Key type outside the baseline cert_type_not_allowed
The certificate’s key type is outside the baseline, such as DSA or EdDSA. Issue an RSA or ECDSA certificate.
Required by: Mozilla (certificate_types), BSI (§3.3.3 Table 7), NIST (§3.2), NCSC-NL (Table 2: Insufficient).
Curve outside the baseline curve_not_allowed
The certificate’s curve is outside the baseline. Issue it on P-256 or P-384.
Required by: Mozilla (certificate_curves), BSI (§3.6.2), NIST (§3.2, Table 3-1), NCSC-NL (Tables 3, 5: Insufficient).
Certificate valid for too long long_lifespan
The certificate is valid for longer than the baseline allows. Issue shorter-lived certificates, ideally renewed automatically.
Required by: Mozilla (maximum_certificate_lifespan), NIST (Table 3-1).
Wildcard name in the certificate wildcard
The certificate covers a wildcard name. A wildcard key is shared by every host it covers, so one compromised host exposes all of them. Prefer certificates for named hosts.
Required by: BSI (TR-02103 (1.0) §4.1.2).
No Key Usage extension no_key_usage
The certificate has no Key Usage extension. Ask your CA for a certificate that sets it.
Required by: BSI (TR-02103 (1.0) Table 30), NIST (Table 3-1).
Key Usage not critical key_usage_not_critical
The certificate’s Key Usage is not marked critical. Ask your CA for one that marks it.
Required by: BSI (TR-02103 (1.0) Table 34), NIST (Table 3-1).
Key Usage does not fit the key exchange key_usage_mismatch
The certificate’s Key Usage does not allow the key exchange the server uses, for example RSA key transport with a signing-only key. Remove the RSA key transport suites, or reissue the certificate.
Required by: BSI (TR-02103 (1.0) §4.1.3), NIST (Table 3-1).
No Extended Key Usage no_server_auth_eku
The certificate has no Extended Key Usage. Ask your CA for one that names TLS server authentication.
Required by: BSI (TR-02103 (1.0) §4.1.4), NIST (Table 3-1).
Extended Key Usage allows any purpose eku_any_purpose
The certificate’s Extended Key Usage allows any purpose. Ask your CA for one limited to TLS server authentication.
Required by: NIST (Table 3-1).
No Authority Key Identifier no_aki
The certificate has no Authority Key Identifier, which helps clients build the chain. Ask your CA for a certificate that has one.
Required by: BSI (TR-02103 (1.0) Table 30), NIST (Table 3-1).
No OCSP responder no_ocsp_responder
The certificate names no OCSP responder. Many CAs have stopped running OCSP, so this is only a finding where a baseline requires it.
Required by: NIST (§3.2, Table 3-1).
DNS
No CAA records no_caa
The name has no CAA records, so any CA may issue certificates for it. Publish a CAA record naming the CAs you use.
Required by no baseline: recorded and graded only.
No Encrypted Client Hello no_ech
The name’s HTTPS DNS record does not advertise Encrypted Client Hello. Recorded only; it never costs a lock, since it depends on your CDN as much as on you.
Required by no baseline: recorded and graded only.
Revocation
No OCSP stapling no_ocsp_stapling
The certificate names an OCSP responder and the server staples no response, so each client has to ask the CA. In nginx: ssl_stapling on; In Apache: SSLUseStapling on.
Required by: Mozilla (ocsp_staple), NIST (§3.4.1.5).
HTTP
No HSTS header no_hsts
The HTTPS response carries no Strict-Transport-Security header, so a browser sent to plain HTTP by a typed address or an old link can be intercepted before it reaches HTTPS. Send the header on every HTTPS response. In nginx: add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
Required by: Mozilla (hsts_min_age).
HSTS max-age too short short_hsts
The HSTS max-age is shorter than asked: two years under Mozilla, one year for the fifth lock. Browsers remember the header for that long, so raise it once HTTPS works everywhere on the name.
Required by: Mozilla (hsts_min_age).
HSTS leaves out subdomains hsts_no_subdomains
The HSTS header leaves subdomains out, so a subdomain reached over plain HTTP can still set cookies for the whole domain. Add includeSubDomains once every subdomain serves HTTPS.
Required by no baseline: recorded and graded only.
No redirect to HTTPS no_https_redirect
Port 80 answers without sending visitors to HTTPS on the same name: it serves the page over plain HTTP, redirects to plain HTTP, or redirects to another name first. Redirect every plain-HTTP request to https:// on the same name; move to another name afterwards, over HTTPS. A closed port 80 is not a finding.
Required by no baseline: recorded and graded only.
Redirect to HTTPS not permanent redirect_not_permanent
Port 80 redirects to HTTPS with a temporary status (302, 303 or 307), so browsers and search engines keep coming back over plain HTTP. Use 301 or 308. In nginx: return 301 https://$host$request_uri;
Required by no baseline: recorded and graded only.
Cookies without Secure insecure_cookie
The HTTPS response sets cookies without the Secure attribute, so a browser also sends them over plain HTTP, where anyone on the path can read them. Set Secure on every cookie; the finding names them. Their values are never stored.
Required by no baseline: recorded and graded only.
Obsolete pinning headers obsolete_pinning
The response carries Public-Key-Pins or Expect-CT. Browsers dropped both years ago, and a forgotten pin header can still lock out a client that honoured it. Remove them: browsers enforce Certificate Transparency without the header, and a mobile app pins keys in its own code.
Required by no baseline: recorded and graded only.
Probe coverage
Configuration test incomplete posture_incomplete
The daily configuration test could not establish everything: a probe was not sent or got no answer, the server accepted more cipher suites than the test lists, or a certificate was too large to keep. No baseline is counted as met on what the test did not see, so the grade stays at three locks while a selected baseline is affected, and below five otherwise. It usually clears with the next day’s test; if it stays, check that the server answers every connection rather than dropping some. With the HTTP checks on, an HTTPS request that got no answer counts the same way; switch them off for a port that does not serve HTTP.
Required by no baseline: recorded and graded only.