dotvitals

Rule catalogue

The 292 checks a dotvitals scan runs. Each one states a condition, what it costs your score when it is true, why it matters and how to put it right.

Ruleset 2026.09.9 ·how the score is calculated

Filter

Email authentication (40)

  • BIMI is published but DMARC is not enforcing

    You have a BIMI record, but your DMARC policy is not strict enough for it to be used.

    email.bimi.dmarc-not-enforcing

    Medium−6
  • BIMI logo is not a valid SVG Tiny Portable/Secure file

    Your logo is not in the restricted SVG format BIMI requires. Mailbox providers reject anything else, so the logo is not shown.

    email.bimi.logo-not-svg-tiny-ps

    Medium−5
  • BIMI logo URL cannot be fetched

    The logo your BIMI record points at could not be downloaded. Mailbox providers that cannot fetch it simply show no logo.

    email.bimi.logo-unreachable

    Medium−5
  • BIMI record has no mark certificate

    Your BIMI record points at a logo but not at a mark certificate. Gmail, Apple Mail and Yahoo will not show the logo without one, so most recipients see…

    email.bimi.no-mark-certificate

    Infonot scored
  • No BIMI record published

    You have not published a BIMI record, so your logo does not appear next to your messages in the inboxes that support it.

    email.bimi.no-record

    Infonot scored
  • BIMI record has a syntax error

    A BIMI record is published but cannot be read, so no inbox will show your logo. The setup looks complete from the DNS side and does nothing.

    email.bimi.syntax-invalid

    Medium−5
  • DKIM key is only 1024 bits

    Your signing key still works, but it is at the minimum size the standard allows. Larger keys are now the norm and some receivers treat 1024-bit signatures as…

    email.dkim.key-1024-bit

    Low−5
  • DKIM record has an empty p= tag (key revoked)

    The DKIM record for this selector exists but contains no key. An empty key means revoked, so every message signed with this selector is rejected outright.

    email.dkim.key-revoked

    Critical−25
  • DKIM key is shorter than 1024 bits

    The signing key published for your domain is too small to be trusted. Receiving servers are told to reject keys this short, so your signature may be treated…

    email.dkim.key-too-short

    High−15
  • No DKIM key found for any known selector

    We could not find a DKIM signing key published for your domain. DKIM is the cryptographic signature that proves a message really came from you and was not…

    email.dkim.no-selector-found

    High−25
  • DKIM record cannot be parsed

    The record published for this selector is not a valid DKIM key record, so receivers cannot verify signatures made with it.

    email.dkim.syntax-invalid

    High−18
  • DKIM record is in testing mode (t=y)

    Your DKIM record tells receivers to ignore any failures because you are still testing. Left in place, it means a genuine signature failure is never acted on.

    email.dkim.testing-flag-set

    Low−4
  • DKIM key uses an algorithm receivers reject

    Your key is published with a signing algorithm that receiving servers no longer accept, so signatures made with it are not verified.

    email.dkim.unsupported-algorithm

    Medium−10
  • DMARC reports are sent to an unauthorised external domain

    Your reports are addressed to a mailbox on a different domain, and that domain has not published the record that says it agrees to receive them.

    email.dmarc.external-rua-unauthorised

    Medium−8
  • DMARC requests forensic reports (ruf)

    Your record asks receivers to send you copies of individual failing messages. Few receivers do this, and the ones that do may send you other people's…

    email.dmarc.forensic-reporting-enabled

    Infonot scored
  • Subdomain has no DMARC record and inherits the parent policy

    This subdomain publishes no DMARC record of its own, so receivers apply the policy from your main domain. That is normal and usually what you want.

    email.dmarc.inherited-from-parent

    Infonot scored
  • More than one DMARC record published

    Two or more DMARC records exist at the same name. The rules tell receivers to ignore all of them, so your domain effectively has no DMARC policy.

    email.dmarc.multiple-records

    High−20
  • No DMARC record published

    Your domain does not publish a DMARC policy, so receiving mail servers have no instruction about what to do with mail that fails your other checks.

    email.dmarc.no-record

    Critical−25
  • DMARC record requests no aggregate reports

    Your DMARC record has no address for receivers to send reports to, so you have no way of finding out who is sending mail as your domain or whether it passes.

    email.dmarc.no-rua

    Low−4
  • DMARC record still carries a pct tag

    Your policy is enforcing, but it still carries the old `pct` tag asking receivers to apply it to only some messages.

    email.dmarc.pct-below-100

    Medium−6
  • DMARC policy is p=none (monitor only)

    Your domain publishes a DMARC record, but it tells receivers to take no action on messages that fail authentication.

    email.dmarc.policy-none

    High−15
  • Subdomains are exempt from an enforcing DMARC policy

    Your main domain is protected, but the record explicitly exempts every subdomain. Attackers routinely spoof a subdomain that was never used for mail, because…

    email.dmarc.subdomain-policy-none

    Medium−10
  • DMARC record has a syntax error

    The record at _dmarc cannot be read as a valid DMARC policy, so receivers discard it and treat your domain as having no policy.

    email.dmarc.syntax-invalid

    High−20
  • DMARC is in test mode, so the policy is not applied

    Your record states a policy and then, with `t=y`, asks receiving mail servers not to act on it.

    email.dmarc.test-mode

    High−14
  • SPF authorises the whole internet through an address range

    Your SPF record authorises an address range so wide that it covers the internet itself.

    email.spf.catch-all-range

    Critical−35
  • SPF record lists the same sender twice

    The same entry appears more than once in your SPF record. It has no extra effect, and if it is one that costs a DNS lookup it brings you closer to the limit…

    email.spf.duplicate-mechanism

    Low−3
  • SPF include chain contains a loop

    One of the records your SPF policy pulls in eventually points back at a record already in the chain.

    email.spf.include-loop

    High−20
  • SPF include target has no SPF record

    Your SPF record refers to another domain that does not publish an SPF record of its own.

    email.spf.include-unresolvable

    High−15
  • SPF is close to the 10 DNS lookup limit

    Your SPF record still works, but it is close to the maximum number of DNS lookups allowed.

    email.spf.lookups-near-limit

    Medium−8
  • More than one SPF record published

    Two or more SPF records exist for your domain. The rules say a receiver must treat this as an error, so in practice none of them is applied and your SPF is…

    email.spf.multiple-records

    High−25
  • SPF record has no all mechanism

    Your SPF record lists authorised senders but never says what to do about everyone else.

    email.spf.no-all

    Medium−10
  • No SPF record published

    Your domain does not tell receiving mail servers which computers are allowed to send email for it.

    email.spf.no-record

    High−25
  • SPF authorises a very large block of addresses

    Your SPF record authorises a huge range of internet addresses to send mail as you.

    email.spf.overly-broad-range

    Medium−6
  • SPF ends in +all — anyone may send as your domain

    Your SPF record explicitly authorises every server on the internet to send mail as your domain.

    email.spf.plus-all

    Critical−35
  • SPF uses the deprecated ptr mechanism

    Your SPF record uses a mechanism the standard tells people not to use. It is slow, it puts load on other people's DNS servers, and some receivers ignore it…

    email.spf.ptr-mechanism

    Low−4
  • SPF ends in ?all (neutral)

    Your SPF record ends by telling receivers to form no opinion about servers that are not on your list.

    email.spf.question-all

    Medium−10
  • SPF has both redirect= and an all mechanism

    Your record contains a redirect to another domain's policy and also its own closing rule.

    email.spf.redirect-with-all

    Medium−6
  • SPF record has a syntax error

    Your SPF record cannot be read by receiving mail servers. Because it is unreadable, the whole check fails with an error and none of your listed senders is…

    email.spf.syntax-invalid

    High−20
  • SPF needs more than 10 DNS lookups

    Evaluating your SPF record requires more DNS lookups than the standard allows. Receiving servers stop early and return an error, so your SPF check does not…

    email.spf.too-many-lookups

    High−20
  • SPF exceeds the void DNS lookup limit

    Too many of the lookups in your SPF record point at names that do not exist. Receivers stop evaluating and return an error, so the record authenticates…

    email.spf.void-lookups-exceeded

    Medium−10

Email transport (33)

  • MTA-STS max_age is very short

    Your policy asks senders to forget it again after a short time. A short lifetime narrows the window in which the policy actually protects you.

    email.mta-sts.max-age-too-low

    Low−3
  • MTA-STS policy mode is none

    Your published policy explicitly tells senders to ignore any previous policy for your domain. It provides no protection at all.

    email.mta-sts.mode-none

    Medium−8
  • MTA-STS policy is still in testing mode

    Your policy is published but asks senders only to report problems, not to act on them. Mail can still be delivered unencrypted.

    email.mta-sts.mode-testing

    Low−4
  • A live MX host is not listed in the MTA-STS policy

    One of your mail servers is missing from the policy. If the policy is enforcing, senders will refuse to deliver to that server and mail to your domain…

    email.mta-sts.mx-not-covered

    High−12
  • No MTA-STS policy published

    Mail sent to your domain is encrypted only if the sending server happens to try. An attacker positioned on the network can strip that encryption and read the…

    email.mta-sts.no-record

    Medium−10
  • MTA-STS policy file is malformed

    The policy file exists but cannot be understood. Senders discard it and go back to unencrypted delivery.

    email.mta-sts.policy-invalid

    High−12
  • MTA-STS policy file cannot be fetched

    Your domain announces an MTA-STS policy but the policy file itself cannot be downloaded. Senders that cannot fetch it fall back to unencrypted delivery.

    email.mta-sts.policy-unreachable

    High−12
  • MTA-STS DNS record is malformed

    The DNS record that announces your MTA-STS policy cannot be read, so senders never look for the policy file.

    email.mta-sts.record-invalid

    High−10
  • Two MX hosts share the same preference value

    Two of your mail servers are given the same priority, so senders will spread mail across both at random. That is only correct if both really are equivalent.

    email.mx.duplicate-preference

    Low−3
  • MX record points at a CNAME

    One of your mail server records points at an alias rather than a real host. The standard forbids this, and some sending servers refuse to follow it.

    email.mx.host-is-cname

    Medium−12
  • MX record points at an IP address instead of a hostname

    One of your mail server records contains an IP address where a hostname is required. Many sending servers will not deliver mail to it at all.

    email.mx.host-is-ip

    High−20
  • Mail server address has no reverse DNS name

    The address behind one of your mail servers has no reverse DNS entry. Many receiving systems treat that as a spam signal when this machine also sends mail.

    email.mx.host-no-rdns

    Low−2
  • MX host does not resolve to an address

    One of your mail servers is named in DNS but that name has no address, so nothing can connect to it. Mail directed there fails.

    email.mx.host-unresolvable

    High−20
  • No MX record — this domain cannot receive email

    Your domain publishes no mail server records, so nobody can send email to any address at it. Messages bounce back to the sender.

    email.mx.no-record

    Critical−30
  • Every mail server resolves to the same address

    You publish more than one mail server, but they all point at the same machine. If it goes down, the backup goes down with it and inbound mail is delayed or…

    email.mx.no-redundancy

    Medium−8
  • Domain publishes a null MX (receives no mail)

    Your domain explicitly declares that it does not accept email. That is a valid and useful configuration for a domain that only hosts a website.

    email.mx.null-mx

    Infonot scored
  • Only one mail server host is published

    All of your inbound mail depends on a single server. If it is unreachable, senders queue messages and eventually give up, and some mail is lost.

    email.mx.single-host

    Medium−8
  • Reverse DNS looks like a generic provider-assigned name

    Your mail server's reverse name looks automatically generated rather than chosen — the sort of name a provider mints for a whole block of addresses.

    email.rdns.generic-hostname

    Low−5
  • Reverse DNS name does not match the mail server's own hostname

    The name in your mail server's reverse DNS is different from the name your MX record points at.

    email.rdns.name-mismatch

    Low−4
  • Mail server address has no reverse DNS (PTR) record

    One of the addresses your mail server uses has no name attached to it. Many large mail providers reject or heavily filter mail from an address with no…

    email.rdns.no-ptr

    High−20
  • Reverse DNS does not confirm forward (no full-circle match)

    Your mail server's address has a name attached, but that name does not resolve back to the same address.

    email.rdns.not-forward-confirmed

    Medium−12
  • Mail server's SMTP greeting does not conform to the protocol

    Your mail server's opening greeting is not shaped the way the standard requires — it is over-long, contains characters it should not, or does not start with…

    email.smtp-tls.banner-malformed

    Low−3
  • Mail server's TLS certificate has expired or is not yet valid

    The certificate your mail server presents is outside its validity dates. Senders that verify certificates will refuse to deliver mail to you.

    email.smtp-tls.certificate-expired

    High−20
  • Mail server's certificate does not cover its own hostname

    The certificate your mail server presents is for a different name than the one your MX record points at.

    email.smtp-tls.certificate-name-mismatch

    Medium−15
  • Mail server's TLS certificate does not verify

    Your mail server encrypts, but its certificate is self-signed or issued by an authority senders do not trust, so senders cannot tell they are talking to you…

    email.smtp-tls.certificate-untrusted

    Medium−15
  • Mail server does not offer STARTTLS

    Your mail server does not offer encryption, so mail sent to this domain crosses the internet in plain text where anyone on the path can read it.

    email.smtp-tls.no-starttls

    High−25
  • Mail server does not accept connections on port 25

    Your mail server did not answer on the port email is delivered to. If this is not a temporary fault, inbound mail to this domain is not arriving.

    email.smtp-tls.port-unreachable

    Critical−30
  • SMTP transport security was not tested

    We could not test your mail servers' encryption on this scan. Nothing below was measured — this is a gap in our result, not a finding about your mail.

    email.smtp-tls.probe-unavailable

    Infonot scored
  • STARTTLS is advertised but the handshake does not complete

    Your mail server offers encryption and then fails to deliver it. This is worse than not offering it: senders that saw the offer may refuse to fall back to…

    email.smtp-tls.starttls-failed

    High−25
  • Mail server negotiates a deprecated TLS version

    Your mail server agreed to an old, deprecated version of TLS. It still encrypts, but with a protocol that has known weaknesses and that senders are actively…

    email.smtp-tls.weak-protocol

    Medium−10
  • No TLS-RPT record published

    Nobody tells you when encrypted delivery to your mail servers fails. Senders that could not connect securely simply do not, and you never find out.

    email.tls-rpt.no-record

    Low−4
  • TLS-RPT record has a syntax error

    The record exists but cannot be read, so no reports are sent. You have the appearance of TLS reporting without the reporting.

    email.tls-rpt.syntax-invalid

    Medium−4
  • TLS-RPT HTTPS report endpoint is unreachable

    Your record asks for reports to be posted to a web address that does not accept them. The reports are generated and then thrown away.

    email.tls-rpt.uri-unreachable

    Medium−4

Email reputation (5)

  • Listed on a source we show but do not score

    One of your mail server addresses appears on {{listName}}. We show this because it is real, but it does not affect your score — this list often lists whole…

    email.blocklists.advisory-listing

    Infonot scored
  • Which blocklists we check, and which we do not

    We check {{checkedLists}}. We do not check {{excludedLists}} — not because we cannot, but because their free feeds are licensed for non-commercial use and we…

    email.blocklists.coverage-limited

    Infonot scored
  • Domain is listed on a domain reputation blocklist

    Your domain name itself appears on a reputation blocklist. Unlike an address listing, this follows the domain everywhere — changing servers does not clear it.

    email.blocklists.domain-listed

    Critical−40
  • A blocklist did not answer, so it is not counted as clean

    {{listName}} {{outcome}} for {{address}}. That is not evidence you are clean — it means we do not know, and the result above is scoped to the lists that did…

    email.blocklists.list-unavailable

    Infonot scored
  • Mail server address is listed on a blocklist

    One of your mail server addresses appears on {{listName}}. Receivers that consult that list will reject or quarantine mail from this address until it is…

    email.blocklists.mx-ip-listed

    Critical−40

DNS (38)

DNSSEC (14)

Domain registration (12)

  • The domain registration has expired

    The registry's expiry date for this domain is in the past. Depending on how long ago, the domain may already have stopped resolving, and after a grace period…

    domain.rdap.expired

    Critical−90
  • The domain registration expires within 30 days

    The registry's expiry date for this domain is under a month away. This is normal for a domain that auto-renews — it is worth one check that the renewal will…

    domain.rdap.expiring-lt-30d

    High−30
  • The domain registration expires within 7 days

    The registry's expiry date for this domain is less than a week away. If the automatic renewal does not go through, the domain starts down the deletion path…

    domain.rdap.expiring-lt-7d

    Critical−70
  • The domain registration expires within 90 days

    The registry's expiry date is roughly a quarter away. This is a note, not a problem: it is the normal state of a domain approaching its renewal, and it…

    domain.rdap.expiring-lt-90d

    Infonot scored
  • No transfer lock is set on the domain

    The registry shows no `clientTransferProhibited` status, so nothing at your registrar has to be unlocked before a transfer request to another registrar can…

    domain.rdap.no-registrar-lock

    High−25
  • No update lock is set on the domain

    The registry shows no `clientUpdateProhibited` status, so the domain's nameservers and contact details can be changed from inside the registrar account with…

    domain.rdap.no-update-lock

    Medium−10
  • The domain is suspended by the registrar or registry

    A `clientHold` or `serverHold` status means the domain has been pulled from the zone deliberately.

    domain.rdap.on-hold

    Critical−90
  • The domain is scheduled for deletion

    The redemption window has closed and the registry has queued the domain for release — usually about five days.

    domain.rdap.pending-delete

    Critical−90
  • The domain is in the redemption period

    The domain expired, was deleted, and is in the roughly 30-day window in which the previous owner can still get it back — by asking the registrar for a…

    domain.rdap.redemption-period

    Critical−80
  • The registrant contact details are not published

    The registry does not publish who holds this domain. That is the normal, expected state for an individual registrant, it is not a misconfiguration, and it…

    domain.rdap.registrant-redacted

    Infonot scored
  • The registration data could not be read

    We could not get a registration record for this domain, so nothing in this section was checked.

    domain.rdap.registration-data-unavailable

    Infonot scored
  • The registration is current and locked

    The registry shows a comfortable expiry date, a transfer lock in place, and no suspension or deletion status. This is what a well-kept domain looks like.

    domain.rdap.registration-healthy

    Infonot scored

TLS (25)

  • Certificate chain is missing an intermediate

    The server sent its own certificate but not the linking certificates above it. Some visitors see the site fine and others get a security warning, seemingly…

    tls.certificate.chain-incomplete

    High−25
  • Certificate chain is not in the required order

    The linking certificates are present but sent in the wrong order, or one is repeated. Modern clients cope; older and stricter ones do not.

    tls.certificate.chain-out-of-order

    Low−5
  • TLS certificate has expired

    The certificate's end date has passed. Every browser now shows a full-page security warning instead of your site, and most visitors will not click through it.

    tls.certificate.expired

    Critical−60
  • TLS certificate expires in under 30 days

    The certificate still works, but it runs out within the month. This is the point where automatic renewal should already have replaced it.

    tls.certificate.expiring-lt-30d

    Medium−10
  • TLS certificate expires in under 7 days

    The certificate is about to run out. If renewal has not already succeeded, your site goes down within the week.

    tls.certificate.expiring-lt-7d

    High−25
  • Certificate does not cover the hostname

    The certificate is for a different name than the one visitors type. Browsers show a security warning and refuse to continue without an explicit override.

    tls.certificate.hostname-mismatch

    Critical−60
  • Certificate has no Subject Alternative Name

    The certificate lists its hostname only in the old Common Name field, which browsers stopped reading in 2017.

    tls.certificate.no-san

    Medium−10
  • TLS certificate is not valid yet

    The certificate's start date is in the future, so browsers reject it exactly as they would reject an expired one.

    tls.certificate.not-yet-valid

    High−30
  • Certificate is self-signed

    The certificate vouches for itself. Nobody else has confirmed the site is who it says it is, so browsers treat it as untrusted.

    tls.certificate.self-signed

    Critical−55
  • Certificate could not be parsed

    The server sent something in place of a certificate that could not be read as one. No client can validate what it cannot decode.

    tls.certificate.unreadable

    Medium−20
  • Certificate does not chain to a trusted root

    The certificate cannot be traced back to an authority browsers trust, so it is rejected the same way an expired or mismatched one is.

    tls.certificate.untrusted-root

    Critical−60
  • Certificate is valid for longer than a public CA may issue

    The certificate's lifetime is longer than any publicly trusted authority is allowed to grant, which means it did not come from one.

    tls.certificate.validity-too-long

    Low−5
  • Certificate uses a key that is too small

    The certificate's key is smaller than the current minimum, so the encryption protecting the site is weaker than it should be.

    tls.certificate.weak-key

    High−25
  • Certificate is signed with a broken hash algorithm

    The certificate is signed using an outdated method that can be forged. Browsers have rejected these since 2017.

    tls.certificate.weak-signature-algorithm

    High−30
  • Certificate uses an unusually broad wildcard

    The certificate covers a very wide range of names. If its private key ever leaks, the damage extends far beyond this one site.

    tls.certificate.wildcard-too-broad

    Low−4
  • Server accepts a broken cipher suite

    One of the encryption methods the server agrees to is broken — it can be read, forged, or provides no protection at all.

    tls.protocols.insecure-cipher

    High−30
  • Some connections have no forward secrecy

    For some connections the server uses a method where one leak of its private key would expose every past conversation that anyone recorded.

    tls.protocols.no-forward-secrecy

    Medium−15
  • Neither TLS 1.2 nor TLS 1.3 is supported

    The server offers only versions of TLS that browsers have already removed. Most visitors cannot connect at all.

    tls.protocols.no-tls12

    High−40
  • TLS 1.3 is not supported

    The server does not offer the current version of TLS. Connections still work over the older version, but they are slower to set up and lack its safety…

    tls.protocols.no-tls13

    Medium−8
  • Protocol and cipher support could not be tested

    We could not run the handshakes needed to find out which TLS versions this server accepts, so this part of the report is missing rather than clear.

    tls.protocols.probe-unavailable

    Infonot scored
  • SSL 2.0 is enabled

    The server still accepts a protocol from 1995 that is completely broken. Its presence weakens the modern connections too.

    tls.protocols.sslv2-enabled

    Critical−60
  • SSL 3.0 is enabled

    The server accepts SSL 3.0, which has been formally prohibited since 2015 and can be attacked to reveal parts of an encrypted session.

    tls.protocols.sslv3-enabled

    Critical−50
  • TLS 1.0 is enabled

    The server still accepts TLS 1.0, a version from 1999 that browsers removed in 2020. Keeping it available lets a connection be pushed down to it.

    tls.protocols.tls10-enabled

    High−25
  • TLS 1.1 is enabled

    The server accepts TLS 1.1, which browsers removed alongside TLS 1.0 in 2020. It offers nothing TLS 1.2 does not.

    tls.protocols.tls11-enabled

    High−20
  • Server accepts a weak cipher suite

    One of the encryption methods on offer is outdated. It is not trivially broken, but it has known weaknesses and nothing current needs it.

    tls.protocols.weak-cipher

    Medium−10

HTTP (25)

  • The caching instructions contradict each other

    The response asks for two different things at once — for example, do not reuse this, and also reuse it for an hour.

    http.headers.cache-directives-conflicting

    Low−5
  • A text response does not declare its character encoding

    The response says it is text but not which alphabet it is written in, so the browser works it out from the bytes.

    http.headers.charset-missing

    Low−4
  • The declared Content-Encoding may not match the body

    The response claims to be compressed, but the body we measured was the same size as the uncompressed one.

    http.headers.compression-encoding-mismatch

    Medium−6
  • A compressible response was sent uncompressed

    This page is text, it is big enough to be worth compressing, and we asked for a compressed copy — the server sent it in full anyway.

    http.headers.compression-not-applied

    Medium−8
  • The response has a body but no Content-Type

    The server sent content without saying what kind of content it is, so each browser guesses.

    http.headers.content-type-missing

    Medium−10
  • The response sends obsolete headers, one of them harmful

    Some of these headers do nothing at all now. One of them switches on a browser feature that was removed because it could itself be used to attack the page.

    http.headers.deprecated-header-present

    Low−3
  • No Alt-Svc header advertises HTTP/3

    The response does not mention that an HTTP/3 endpoint is available. This is a note, not a problem — and it only tells you what was advertised, not what your…

    http.headers.http3-not-advertised

    Infonot scored
  • A response header leaks an internal address

    One of your headers contains an address from inside your own network — a private IP or an internal-only hostname.

    http.headers.internal-address-disclosed

    Medium−8
  • The response does not say how long it may be cached

    Your page arrives with no caching instructions, so browsers and networks in between invent their own.

    http.headers.no-cache-control

    Low−6
  • The response cannot be revalidated without downloading it again

    Your response carries no fingerprint, so a browser holding an old copy has no way to ask 'has this changed?'. It has to download the whole thing to find out.

    http.headers.no-validator

    Low−4
  • A compressed response does not vary on Accept-Encoding

    The server sends different versions of this page depending on what the visitor's browser can unpack, but it does not tell shared caches that.

    http.headers.vary-missing-accept-encoding

    Low−5
  • Vary: * makes the response uncacheable by any shared cache

    This response tells every shared cache and CDN never to reuse it. If you are paying for a CDN in front of this site, this header is switching it off.

    http.headers.vary-wildcard

    Low−4
  • The site's home page returns an error status

    The address answered, but with an error code rather than a page. Visitors landing on the home page see an error.

    http.reachability.error-status

    Medium−10
  • Plain HTTP is not served at all

    Nothing answers on the insecure port. That is a safe configuration — there is no unencrypted request to intercept — with one practical caveat.

    http.reachability.http-closed

    Infonot scored
  • Plain HTTP does not redirect to HTTPS

    The insecure port serves the site instead of sending visitors to the secure one. Anyone typing your address without `https://` gets an unencrypted page.

    http.reachability.http-open-no-redirect

    High−30
  • The site does not answer over HTTPS

    Nothing responded on the secure port. Either the site is down, the encrypted service is not running, or something between us and it is blocking the…

    http.reachability.https-unreachable

    Critical−60
  • The server was slow to respond

    The home page took noticeably long to start responding. Visitors feel this as the site hanging before anything appears.

    http.reachability.slow-response

    Low−5
  • The redirect chain is longer than it needs to be

    Visitors are bounced through several addresses before reaching the page. Each bounce is a full round trip they wait for.

    http.redirects.chain-too-long

    Low−6
  • The chain moves between hostnames

    Visitors are handed from one hostname to another along the way. That is normal — it is how `www` redirects and content networks work — and it is recorded…

    http.redirects.cross-host-hop

    Infonot scored
  • A redirect pointed somewhere the scanner will not follow

    One step of the chain led to an address we refuse to connect to — a private network address, a cloud metadata endpoint, or an internal-only name.

    http.redirects.hop-refused

    Medium−12
  • The redirect chain loops

    The site sends visitors in a circle: one address redirects to another, which redirects back. Browsers give up and show an error instead of the page.

    http.redirects.loop

    High−40
  • A redirect destination is malformed

    The address the server redirected to is not a usable web address. Browsers may refuse it, or may interpret it in a way you did not intend.

    http.redirects.malformed-location

    Medium−20
  • A redirect response has no destination

    The server said 'go somewhere else' without saying where. Browsers show a blank page or an error.

    http.redirects.missing-location

    Medium−20
  • A redirect drops from HTTPS to plain HTTP

    Part of the journey moves visitors from the secure address back to the insecure one. Whatever they send after that point travels in the clear.

    http.redirects.protocol-downgrade

    High−30
  • A permanent redirect is marked temporary

    The redirect between your `www` and non-`www` addresses says 'this is temporary'. Browsers and search engines therefore keep asking for the old address every…

    http.redirects.temporary-for-canonical

    Low−5

Web security (42)

  • Cookie sets a Domain the browser will not accept, so it is discarded

    The cookie names a domain that this host is not part of. A browser does not narrow the scope in that case — it throws the whole cookie away, so the cookie is…

    web.cookies.domain-not-accepted

    High−15
  • Cookie carries an attribute browsers cannot read

    Part of the cookie's definition is not valid. Browsers ignore the unreadable part, so the cookie may behave differently from how it was written.

    web.cookies.malformed-attribute

    Low−4
  • Cookie can be read by JavaScript

    This cookie has no HttpOnly flag, so any script running on the page can read it — including a script that was injected.

    web.cookies.no-httponly

    Medium−10
  • Cookie has no SameSite attribute

    You have not said whether this cookie should be sent when another website triggers a request to yours.

    web.cookies.no-samesite

    Medium−8
  • Cookie is sent over unencrypted connections

    This cookie has no Secure flag, so the browser also sends it over plain HTTP. Anyone on the same network can read it from that request.

    web.cookies.no-secure

    High−15
  • The page set no cookies

    No cookies were set on the page we checked. There is nothing to grade here.

    web.cookies.none-set

    Infonot scored
  • Cookie is shared with every subdomain

    The cookie carries a Domain attribute, so it is not scoped to this host alone: every subdomain of that domain receives it too — including ones you may not…

    web.cookies.overly-broad-domain

    Medium−8
  • Cookie name promises protections its attributes do not provide

    The cookie's name starts with a special prefix that browsers enforce rules for, and those rules are not met — so the browser rejects the cookie entirely.

    web.cookies.prefix-requirements-unmet

    Medium−10
  • Cookie uses SameSite=None without Secure, so it is rejected

    This combination is invalid and browsers throw the cookie away. Whatever it was for is not working.

    web.cookies.samesite-none-insecure

    High−15
  • The CORS policy accepts any request header from any origin

    The preflight said another site may send any header it likes with its request — on a policy that does not restrict which sites may ask.

    web.cors.headers-overly-broad

    Low−4
  • The Access-Control-Allow-Origin value is not a valid origin

    The header is there but its value is not something a browser can use — several origins at once, a trailing slash, a path, or a hostname with no https:// in…

    web.cors.malformed-allow-origin

    Medium−6
  • The CORS policy grants broad methods on an unrestricted origin

    The preflight said which HTTP methods another site may use, and the list includes ones that change or delete data — on a policy that does not restrict which…

    web.cors.methods-overly-broad

    Low−4
  • The null origin is on the CORS allow-list

    The server allows an origin called `null`. That is not a website — it is what the browser sends for sandboxed frames and local files, and any page on the…

    web.cors.null-origin-allowed

    High−15
  • Any website is allowed to read this site's responses

    The server told a website we invented that it may read this page's contents. It will tell any website the same thing.

    web.cors.origin-reflected

    High−18
  • Any website can read authenticated responses from this site

    We asked for this page while claiming to be a website we made up, and the server said that website is allowed to read the answer — with the visitor's cookies…

    web.cors.origin-reflected-with-credentials

    Critical−30
  • Preflight results are not cached

    Before most cross-origin calls the browser asks permission with a separate request.

    web.cors.preflight-not-cached

    Infonot scored
  • The CORS response varies by origin but is not marked Vary: Origin

    The allowed-origin header changes depending on who asks, but the response does not tell caches that.

    web.cors.vary-origin-missing

    Medium−8
  • Resources are shared with every origin, without credentials

    This endpoint tells every website it may read the response, and no cookies are involved. That is the normal, correct setting for something meant to be public.

    web.cors.wildcard-origin

    Infonot scored
  • The CORS policy pairs a wildcard origin with credentials

    The response says every website is allowed, and also that cookies should be sent. Browsers refuse that combination, so the cross-origin request fails and…

    web.cors.wildcard-with-credentials

    Medium−8
  • No Cross-Origin-Embedder-Policy is set

    The page has not required embedded resources to opt in to being loaded. This is optional and only matters for specific advanced features.

    web.security-headers.coep-missing

    Infonot scored
  • No Cross-Origin-Opener-Policy is set

    Windows your site opens, and windows that open your site, can still reach into each other. Setting this separates them.

    web.security-headers.coop-missing

    Infonot scored
  • No Cross-Origin-Resource-Policy is set

    Other sites may load this page's resources directly. For a public site that is normal; for private content it is worth restricting.

    web.security-headers.corp-missing

    Infonot scored
  • No Content Security Policy is enforced

    Nothing limits where the page may load scripts from. If a script is ever injected — through a comment field, a compromised plugin, or a third-party widget —…

    web.security-headers.csp-missing

    High−22
  • The policy leaves plugins or the base URL unrestricted

    Two easily-forgotten parts of the policy are unset. Both are used to work around otherwise strict policies.

    web.security-headers.csp-no-object-or-base

    Low−4
  • The Content Security Policy is report-only

    A policy exists but the browser only reports what it would have blocked. Nothing is actually blocked.

    web.security-headers.csp-report-only

    Medium−8
  • The policy allows eval()

    The policy lets the page turn text into running code. Anything that can control that text can run code on your site.

    web.security-headers.csp-unsafe-eval

    Medium−8
  • The policy allows inline scripts or styles

    The policy permits code written directly into the page. That is the exact form injected code takes, so this removes most of the policy's value.

    web.security-headers.csp-unsafe-inline

    Medium−10
  • The policy allows resources from anywhere

    Part of the policy uses a wildcard, which permits any address at all. That directive restricts nothing.

    web.security-headers.csp-wildcard-source

    Low−6
  • A security header was sent twice with different values

    The same header arrived more than once with conflicting values. Which one applies depends on the browser, so the protection you think you have may not be the…

    web.security-headers.duplicate-conflicting

    Medium−6
  • HSTS max-age is shorter than six months

    The instruction to always use HTTPS expires sooner than it should. A visitor who has not been back for a while makes an insecure first request again.

    web.security-headers.hsts-max-age-too-low

    Medium−8
  • HTTP Strict Transport Security is not in force

    Browsers are not told to always use the secure version of your site. The first visit of every day can still be made over plain HTTP, where it can be…

    web.security-headers.hsts-missing

    High−25
  • HSTS does not cover subdomains

    The always-use-HTTPS instruction applies to this hostname only. Subdomains can still be reached over plain HTTP.

    web.security-headers.hsts-no-subdomains

    Low−5
  • The site is not set up for HSTS preloading

    Browsers only learn to force HTTPS after the first visit. Preloading builds that instruction into the browser itself, so even the very first visit is secure.

    web.security-headers.hsts-not-preloaded

    Infonot scored
  • A response header is malformed

    One of the headers contains something that should not be in a header — a line break, or a value far longer than any header needs.

    web.security-headers.malformed-value

    Medium−8
  • The page can be embedded in another site

    Nothing stops another website from loading your page inside an invisible frame and tricking visitors into clicking things they cannot see.

    web.security-headers.no-frame-protection

    Medium−12
  • No Permissions-Policy is set

    You have not restricted which browser features the page — and anything embedded in it — may use, such as the camera, microphone or location.

    web.security-headers.permissions-policy-missing

    Infonot scored
  • No Referrer-Policy is set

    You have not said how much of your addresses to share when visitors follow a link away from your site.

    web.security-headers.referrer-policy-missing

    Low−3
  • The Referrer-Policy leaks full URLs

    The policy you set sends your complete addresses — including the path and anything after the question mark — to other websites visitors click through to.

    web.security-headers.referrer-policy-weak

    Low−5
  • The server announces its exact version

    Every response says which software you run and which version. That turns 'find a vulnerable site' into a search query.

    web.security-headers.server-version-disclosed

    Low−3
  • Response headers name the application stack

    Headers such as X-Powered-By tell every visitor which framework and version builds your pages. They serve no purpose for the visitor.

    web.security-headers.technology-disclosed

    Low−3
  • Browsers may guess the type of your responses

    Without this header a browser may ignore what you say a file is and decide for itself — which can turn an uploaded image into a running script.

    web.security-headers.xcto-missing

    Medium−8
  • The exact version of your CMS is published on every page

    Your site tells every visitor which version of {{product}} it runs. Anyone can compare that number against the list of known vulnerabilities for it without…

    web.technology.cms-version-disclosed

    Low−5

Network (6)

  • A database port is reachable from the internet

    Port {{port}} on {{host}} accepts connections from anywhere on the internet, and that port is where {{service}} listens.

    net.ports.database-exposed

    Critical−40
  • FTP is reachable from the internet

    Port 21 on {{host}} accepts connections. FTP sends the username, the password and the file contents in clear text, so anyone able to observe the connection…

    net.ports.ftp-exposed

    Medium−12
  • Ports reachable from the internet

    {{summary}} Each one is listed with what normally listens there and whether being reachable from the internet is expected for that service.

    net.ports.open

    Infonot scored
  • No port could be tested

    We were not able to run the port check on {{host}}, so this section reports nothing at all rather than reporting that everything is closed.

    net.ports.probe-unavailable

    Infonot scored
  • A remote desktop service is reachable from the internet

    Port {{port}} on {{host}} accepts connections from anywhere, and that port is where {{service}} listens — remote desktop, either RDP or VNC.

    net.ports.remote-admin-exposed

    High−30
  • SSH is reachable from the internet

    Port 22 on {{host}} accepts connections. This is normal — it is how most servers are administered — and it is worth knowing, because it guarantees a…

    net.ports.ssh-exposed

    Infonot scored

Performance (18)

SEO (33)

  • The page declares more than one canonical URL

    This page names {{count}} different canonical URLs. When a page gives conflicting answers, search engines disregard all of them and decide for themselves.

    seo.canonical.conflicting

    Medium−15
  • The canonical URL cannot be used

    The page declares a canonical, but the value is not a usable web address, so search engines have nothing to act on.

    seo.canonical.invalid

    Medium−10
  • The page declares no canonical URL

    There is no `<link rel="canonical">` on this page. Search engines will choose which version of the URL to show, and their choice may not be the one you would…

    seo.canonical.missing

    Low−6
  • The canonical URL points at a different page

    This page tells search engines that a different URL is the one to index. That is often exactly right — it is how duplicate versions of a page are…

    seo.canonical.points-elsewhere

    Infonot scored
  • The page has no h1 heading

    There is no `<h1>` in the served HTML. The top-level heading is how both readers and assistive technology identify what the page is about.

    seo.headings.h1-missing

    Low−8
  • The heading levels skip a level

    The page jumps from one heading level to a level more than one below it — an `<h4>` directly under an `<h2>`, for example.

    seo.headings.hierarchy-skipped

    Low−4
  • The page has more than one h1

    This page uses {{count}} `<h1>` elements. HTML5 permits this and search engines handle it, so it is reported for you to consider rather than as a fault.

    seo.headings.multiple-h1

    Infonot scored
  • An hreflang annotation is not valid

    {{count}} of the page's `hreflang` links are malformed. Search engines discard the whole annotation set when it cannot be parsed, so the other language…

    seo.hreflang.invalid

    Low−6
  • The hreflang set does not include this page

    The page lists alternate language versions but does not list itself. Google's documentation requires every page in a set to reference every page in the set,…

    seo.hreflang.missing-self-reference

    Low−4
  • The page's declared language is not a well-formed language tag

    `<html lang="{{lang}}">` is not the shape BCP 47 defines for a language tag. A tag that cannot be parsed is discarded, which leaves the page in the same…

    seo.html-lang.invalid

    Low−4
  • The page does not declare what language it is written in

    The `<html>` element carries no `lang` attribute, so nothing in the markup says what language the page is written in.

    seo.html-lang.missing

    Low−5
  • Images on the page have no alt attribute

    {{missing}} of {{total}} images have no `alt` attribute at all. Anyone using a screen reader gets nothing in their place, and image search has no text to…

    seo.images.missing-alt

    Low−6
  • robots.txt blocks this page from being crawled

    Your robots.txt tells crawlers not to fetch this page. They will not read it, so its content cannot be used in search results.

    seo.indexability.blocked-by-robots-txt

    High−30
  • The page tells crawlers not to follow its links

    A `nofollow` directive applies to every link on this page. Crawlers will still read the page, but they will not use its links to find anything else.

    seo.indexability.nofollow

    Medium−10
  • The page asks search engines not to index it

    This page carries a `noindex` directive, which tells search engines to leave it out of their results entirely.

    seo.indexability.noindex

    High−35
  • A noindex directive is unreachable behind a robots.txt block

    This page carries a `noindex` directive and is also blocked in robots.txt. Because crawlers never fetch the page, they never see the directive — so the page…

    seo.indexability.noindex-blocked-by-robots

    High−20
  • The meta description is likely to be truncated or is very short

    The description is {{length}} characters. {{detail}} As with the title, this is about how much is displayed, not about ranking.

    seo.meta-description.length-outside-guidance

    Low−3
  • The page has no meta description

    There is no meta description on this page. Search engines will write the snippet under your result themselves, using text they pick from the page.

    seo.meta-description.missing

    Low−6
  • The page declares the same metadata more than once

    This page carries more than one {{field}}, with different values. Which one is used is decided by the consumer, and different consumers decide differently.

    seo.meta.duplicate-tags

    Low−5
  • The title and the meta description are identical

    The description repeats the title word for word. A search result then shows the same sentence twice, which wastes the only two lines you get.

    seo.meta.title-matches-description

    Low−3
  • Open Graph metadata is missing required properties

    When this page is shared on a social platform or in a chat app, the preview is assembled from Open Graph tags.

    seo.opengraph.incomplete

    Low−5
  • No robots.txt is published

    There is no robots.txt at the site root. This is not a fault — RFC 9309 says a crawler that gets a 404 may access everything — and it is worth knowing…

    seo.robots-txt.missing

    Infonot scored
  • The robots.txt at the site root was not readable as directives

    `/robots.txt` did not return a file a crawler can read: an HTML error page served with a success status, a refusal, a redirect this scan does not follow, or…

    seo.robots-txt.unreadable

    Low−5
  • No XML sitemap could be found

    Neither robots.txt nor the conventional `/sitemap.xml` location produced a sitemap.

    seo.sitemap.missing

    Low−8
  • The sitemap is not declared in robots.txt

    A sitemap was found at the conventional location, but robots.txt does not mention it. Crawlers that do not guess that location will not find it.

    seo.sitemap.not-declared

    Low−3
  • The sitemap URL does not return XML

    Something answers at `{{sitemapUrl}}`, but it is not an XML sitemap. Crawlers will discard it, so the sitemap is effectively missing while appearing to be…

    seo.sitemap.not-xml

    Low−6
  • The page carries no JSON-LD structured data

    No JSON-LD was found. Structured data is optional — it makes a page eligible for enhanced result formats, and its absence costs nothing beyond that…

    seo.structured-data.absent

    Infonot scored
  • A JSON-LD block on the page does not parse

    {{count}} of the page's JSON-LD blocks are not valid JSON, so they are discarded entirely. The markup is present and is doing nothing.

    seo.structured-data.invalid

    Low−8
  • Structured data is missing a documented required property

    The page's {{type}} markup is missing {{property}}, which Google's documentation lists as required.

    seo.structured-data.missing-required-property

    Low−5
  • Structured data uses a type that no longer produces a rich result

    The page marks up {{types}}, which Google no longer shows as an enhanced result. The markup is still valid and harmless — it just no longer earns anything in…

    seo.structured-data.retired-type

    Infonot scored
  • The title is likely to be truncated or is very short

    This page's title is {{length}} characters. {{detail}} This is a display guideline, not a ranking factor — a long title is cut off in the result, not…

    seo.title.length-outside-guidance

    Low−4
  • The page has no title

    There is no `<title>` on this page, or it is empty. The title is the clickable line in a search result and the text in the browser tab, so search engines…

    seo.title.missing

    Medium−12
  • No Twitter card type is declared

    The page declares no `twitter:card`. Most platforms fall back to the Open Graph tags, so a page with good Open Graph metadata usually previews correctly…

    seo.twitter-card.missing

    Infonot scored

Technology (1)

  • Technologies identified from the response

    This is what the site's response and page source suggest it is built with. It is an observation, not a problem, and each entry carries how sure we are.

    web.technology.detected

    Infonot scored