This is a sample. Its subject, example.com, is a domain reserved for documentation — not any customer's site. The judgements, however, are real: synthetic observations were run through the actual evaluation engine to produce it.
Summary Detail
evaluated 01/09/2026 09:00 GMT+9 · 90 / A · coverage 97% · 19 to act on · 2 not inspected · 5 not applicable · 81 compliant
Engine output (verbatim)
no DS record: zone not DNSSEC signed
Score gain: +2 pts
Subjects (1 in total, including any that were not inspected)
Potential risk:
Unsigned, any resolver or on-path device between a visitor and your authoritative servers can substitute answers — pointing your name at their host, or answering the ACME challenge to obtain a genuine certificate for your domain. Signing lets validating resolvers detect that.
dnssec-policy default; in the zone stanza).dig +short DS example.com returns a record, that dig +dnssec example.com @1.1.1.1 comes back with the ad flag, and that dnsviz.net reports no errors.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.dnssec:example.com
example.com in these instructions is a placeholder — read it as your own domain. It is not substituted automatically, because the same text also names real third-party hosts such as letsencrypt.org.
example.com in these instructions is a placeholder — read it as your own domain. It is not substituted automatically, because the same text also names real third-party hosts such as letsencrypt.org.
example.com does not restrict who may frame it
Engine output (verbatim)
framing is not restricted
Score gain: +1 pts
Subjects (1 in total, including any that were not inspected)
Risk detail
A page that does not restrict framing can be laid invisibly over a site the attacker controls. The visitor believes they are clicking the attacker's page and is in fact clicking yours — which matters most where a single click is irreversible, such as confirming a payment or granting access.
Content-Security-Policy: frame-ancestors 'none' (no framing at all) or frame-ancestors 'self' (your own site only).X-Frame-Options: DENY or SAMEORIGIN may be sent alongside it for older browsers; either one satisfies this check.add_header Content-Security-Policy "frame-ancestors 'none'" always;; in Apache, Header always set Content-Security-Policy "frame-ancestors 'none'".curl -sI https://example.com | grep -iE 'frame-ancestors|x-frame-options'.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Host: 192.0.2.1 (example.com - www.example.com)
192.0.2.1 has administrative ports 22 open externally
Engine output (verbatim)
administrative ports open: [22]
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
SSH and management consoles reachable from the whole internet take continuous credential-stuffing traffic; one reused password is a shell on the host. Even unbreached, the banner tells an attacker which version to look up.
ufw allow from 203.0.113.0/24 to any port 22 proto tcp and then ufw deny 22 — but first run ufw status numbered and ufw delete <n> on any pre-existing blanket ALLOW 22, because ufw applies the first matching rule and leaving it there keeps the port open to everyone.listen 127.0.0.1:8080;) and reach them through an SSH tunnel.nmap -Pn -p 22,2222,3000,8080,8443,10000 <ip> reports filtered rather than open.Public index Shodan InternetDBsubject 192.0.2.1collected 01/09/2026 09:00 GMT+9
The index is a record of its last scan, not the current state. evidence id internetdb:internetdb.host:192.0.2.1
0 of example.com's 1 MX hosts have a TLSA (DANE) record
Engine output (verbatim)
no TLSA records for MX hosts
Score gain: +1 pts
Subjects (1 in total, including any that were not inspected)
Risk detail
SMTP falls back to cleartext when an on-path attacker strips the STARTTLS advertisement, and most senders deliver anyway when the certificate does not verify. Without TLSA the sending server has nothing to check the presented key against.
_25._tcp.<mx-host> for each MX — in practice 3 1 1, pinning the public key, with the digest from openssl x509 -in cert.pem -noout -pubkey | openssl pkey -pubin -outform DER | openssl dgst -sha256.dig +dnssec TLSA _25._tcp.mx.example.com returning the ad flag, and posttls-finger -c -L verbose mx.example.com reporting a verified DANE connection.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
example.com has no AAAA record on apex or www, so it is not reachable over IPv6
Engine output (verbatim)
no AAAA on apex or www
Score gain: +1 pts
Subjects (1 in total, including any that were not inspected)
Risk detail
With no AAAA, visitors on IPv6-only and mobile networks reach you through their carrier's translation layer (CGNAT/464XLAT) — infrastructure you do not run, which is both a single point of failure and a place every one of those sessions can be observed.
example.com. 300 IN AAAA 2001:db8::1) and make the server listen on it (nginx listen [::]:443 ssl;, Apache Listen [::]:443).ufw status, ip6tables -S): a host with only IPv4 rules is wide open over IPv6.dig +short AAAA example.com and curl -6 -sI https://example.com.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject www.example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:www.example.com
Engine output (verbatim)
older breach source: [OldLeak]
Score gain: +1 pts
Subjects (1 in total, including any that were not inspected)
Risk detail
A breach attributed to this domain means your users' credentials and personal data are already in circulation. Attackers replay those passwords against your login, VPN and admin panels, and use the personal details to phish the same people convincingly.
Have I Been Pwnedsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id hibp:hibp.breaches:example.com
example.com has no CAA record, so any CA may issue for it
Engine output (verbatim)
no CAA record
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Without CAA, any public CA in the world may issue for this domain. One mis-validated request at any one of hundreds of CAs gives an attacker a genuine, browser-trusted certificate for your name.
example.com. 3600 IN CAA 0 issue "letsencrypt.org" plus 0 iodef "mailto:security@example.com", and 0 issuewild ";" if you issue no wildcards.dig +short CAA example.com.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
Engine output (verbatim)
DMARC p=quarantine
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
`p=none` tells receivers to deliver mail that failed both SPF and DKIM anyway. Anyone can still send convincing invoices and password resets from your domain to your customers and staff; only an enforcing policy makes receivers actually quarantine or drop them.
p=reject._dmarc TXT record in stages: v=DMARC1; p=quarantine; pct=25; rua=..., then pct=100, then p=reject, leaving a full reporting cycle between steps.dig +short TXT _dmarc.example.com showing p=reject, and check the next report shows no rise in rejected legitimate mail.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
MTA-STS mode=testing
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
A declaration whose policy cannot be fetched, is malformed, or is still in `testing` changes nothing for senders: they keep delivering over stripped or unverified connections, which is precisely the position an on-path attacker wants. Only `mode: enforce` makes a sending server refuse to deliver rather than downgrade.
https://mta-sts.example.com/.well-known/mta-sts.txt as text/plain, under a certificate valid for mta-sts.example.com (the apex certificate will not do), containing version: STSv1, mode: enforce, one mx: line per MX host, and max_age: 604800.mode: testing with TLS-RPT for a week or two first to catch MX hosts you left out — an omitted host becomes undeliverable under enforce.id= in the _mta-sts TXT record so senders refetch.curl -s https://mta-sts.example.com/.well-known/mta-sts.txt showing mode: enforce, and that every host from dig +short MX example.com appears in an mx: line.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.mta_sts_policy:example.com
example.com delivers mail to a single MX host
Engine output (verbatim)
mail is delivered to a single MX host
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
With one MX host, mail that arrives while it is down is lost once the sender gives up retrying. How long that takes is the sender's choice, and some implementations stop after a few hours. Purchase orders and password-reset notices disappear during your outage.
example.com. IN MX 20 mx2.example.net..dig +short MX example.com returning two or more distinct host names, and by stopping the first host and watching delivery go to the second.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
example.com's SPF does not end in -all, so senders outside the list are not rejected
Engine output (verbatim)
SPF soft fail (~all)
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
`~all` and `?all` tell receivers to accept mail from servers you never listed and merely mark it; plenty of receivers deliver it, so a forged sender still reaches the inbox. `-all` states that the list is complete and everything else is a forgery.
~all or ?all to -all.-all alone can drop it; what rescues it is DKIM signing plus DMARC's DKIM alignment, so verify DKIM is live on every sender at the same time.dig +short TXT example.com | grep spf1 ending in -all, and check the next DMARC report for legitimate senders that started failing.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
example.com has no TLS-RPT TXT record (_smtp._tls)
Engine output (verbatim)
no TLS-RPT record
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Without TLS-RPT, a sender whose STARTTLS to your MX fails has no way to tell you. An attacker stripping STARTTLS and an expired certificate both pass by as the same quiet cleartext delivery — this record is how you find out that MTA-STS or DANE has broken.
_smtp._tls.example.com reading v=TLSRPTv1; rua=mailto:tlsrpt@example.com (an rua=https://... endpoint also works).dig +short TXT _smtp._tls.example.com, and by receiving the first report a day or two after external mail next arrives.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
example.com issues cookies readable by script: theme
Engine output (verbatim)
cookies readable by script (no HttpOnly): [theme]
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
A cookie without HttpOnly can be read by any JavaScript running on the page. One injected script is then enough to send the session cookie somewhere else. HttpOnly blocks that read, which keeps an injection from escalating into a stolen session.
session.cookie_httponly = 1.cookie: { httpOnly: true } (the default).HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
example.com's response does not carry both cross-origin isolation headers
Engine output (verbatim)
the page is not isolated from other origins
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Without Cross-Origin-Opener-Policy, a page opened through `window.open` and the page that opened it can reach each other's window objects, which gives a page opened from another site a foothold. Without Cross-Origin-Resource-Policy, your resources can be loaded into other sites' pages, leaving room for Spectre-style techniques to infer their contents.
Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Resource-Policy: same-origin.add_header Cross-Origin-Opener-Policy "same-origin" always; and add_header Cross-Origin-Resource-Policy "same-origin" always;.cross-origin for those, or serve them from a separate origin.same-origin-allow-popups instead.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
The response fetched for example.com carries no Content-Security-Policy header
Engine output (verbatim)
content-security-policy missing
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Without a CSP, any script an attacker gets onto the page — through stored XSS, a compromised third-party tag, or a subdomain takeover — runs with the page's full authority over its cookies and its API calls. CSP is what limits where scripts may come from at all.
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; report-uri /csp-report.'unsafe-inline'.Content-Security-Policy.add_header Content-Security-Policy "..." always;; Apache: Header always set Content-Security-Policy "...".curl -sI https://example.com | grep -i content-security-policy and a clean browser console.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
example.com sets no Permissions-Policy, or one that is not valid
Engine output (verbatim)
Permissions-Policy is absent or malformed
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Without this header, a third-party frame embedded in your page inherits whatever camera, microphone and location permission your origin was granted. One advertising or analytics tag is enough for its provider to be in a position to prompt your visitor.
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=().geolocation=(self).add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;.curl -sI https://example.com | grep -i permissions-policy.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
example.com sets no Referrer-Policy, or one that sends the URL to other sites
Engine output (verbatim)
Referrer-Policy is absent or permissive
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
With no policy, or a permissive one, the full current URL travels to any external site the visitor follows a link to. Where that URL carries a session token, a password-reset key, a search term or an internal path, it ends up in a third party's access log.
Referrer-Policy: strict-origin-when-cross-origin — the full URL within your own site, the origin only to other sites, and nothing at all to an unencrypted destination.no-referrer where you want less than that.unsafe-url, no-referrer-when-downgrade and origin-when-cross-origin all leak to third parties and do not pass this check.add_header Referrer-Policy "strict-origin-when-cross-origin" always;.curl -sI https://example.com | grep -i referrer-policy.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
example.com's HTTPS records carry no ECH config (ech=)
Engine output (verbatim)
no ECH config in HTTPS records
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Without ECH the hostname a visitor is connecting to travels in cleartext inside the TLS ClientHello. The content stays encrypted, but a network operator, censor or compromised router can still see which of your hostnames each visitor reached and block them selectively.
ech= parameter in the HTTPS resource record.ech= value in the HTTPS record yourself.dig +short HTTPS example.com showing an ech= parameter.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.https:example.com
DNS answersubject www.example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.https:www.example.com
example.com's HTTPS records do not advertise HTTP/3 (alpn=h3)
Engine output (verbatim)
HTTP/3 not advertised
Score gain: no change
Subjects (1 in total, including any that were not inspected)
Risk detail
Over TCP alone, an attacker on the path can disrupt a session by injecting resets or having a middlebox tear the connection down. QUIC authenticates and encrypts the transport itself, so that no longer works — and advertising it in DNS lets clients use QUIC on the first connection instead of after an Alt-Svc round trip.
example.com. 300 IN HTTPS 1 . alpn="h3,h2" for the apex (and www).listen 443 quic reuseport; beside listen 443 ssl;, set http3 on; and add_header Alt-Svc 'h3=":443"; ma=86400' always;, and open UDP/443 in the firewall, or it silently falls back to TCP.dig +short HTTPS example.com listing alpn="h3" and curl --http3 -sI https://example.com succeeding.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.https:example.com
DNS answersubject www.example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.https:www.example.com
No collection problem was recorded for this run.
Engine output (verbatim)
no malware-feed key is configured, so the feed could not be asked
Score gain: not computed
Reason: This item could not be inspected from publicly available information.
Subjects (1 in total, including any that were not inspected)
Risk detail
A host recorded as distributing malware is serving files that are actually being handed out. Almost always an intruder put them there, and the server is being used as a tool against other people. The victims are third parties; the responsibility sits with the host serving it.
threatsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id threat:threat.intel:example.com
Engine output (verbatim)
no threat-intelligence key is configured, so the service could not be asked
Score gain: not computed
Reason: This item could not be inspected from publicly available information.
Subjects (1 in total, including any that were not inspected)
Risk detail
A listing in Google Safe Browsing puts a red interstitial in front of the site in Chrome, Safari and Firefox alike. Visitors never reach the page. It also drops out of search results and cannot be advertised. The usual causes are a compromised page planting redirects, or malicious content posted through a user-submission feature.
threatsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id threat:threat.intel:example.com
example.com in these instructions is a placeholder — read it as your own domain. It is not substituted automatically, because the same text also names real third-party hosts such as letsencrypt.org.
Engine output (verbatim)
the page links to no document on this site
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
PDF and Office files embed the author's name, who last saved them, the software and version used, and the path the file was saved from. That path carries internal file-server names and account names as they are. To an attacker it is a named individual to target and a sketch of the internal layout.
exiftool -all= file.pdf.This item cites no evidence id.
Engine output (verbatim)
the site links to no public code repository
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A configuration file committed to a public repository hands its credentials to anyone. Making the repository private, or rewriting the history, does not invalidate what has already been taken. Automated harvesting of public repositories runs continuously, and the gap between publication and use is minutes.
git filter-repo, force-push, and ask collaborators to re-clone..gitignore and run a pre-commit scanner (gitleaks, git-secrets).This item cites no evidence id.
Engine output (verbatim)
no BIMI record published; BIMI is optional
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
BIMI puts your logo beside your messages in the recipient's mailbox, which makes a genuine sender visible as one. A record with the wrong syntax simply does not display, leaving your mail looking like anyone else's — including an impersonator's.
default._bimi of the form v=BIMI1; l=https://example.com/logo.svg;.l= tag needs an HTTPS URL for the logo, and the logo must be SVG Tiny Portable/Secure — an ordinary SVG will not render.p=quarantine or stricter.dig +short TXT default._bimi.example.com.This item cites no evidence id.
Engine output (verbatim)
no report address outside this domain
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Sending DMARC aggregate reports to an address outside your own domain requires the receiving domain to publish an authorisation record (RFC 7489 §7.1). Without it, conforming receivers send nothing. It shows up as a perfectly correct report address that never receives a single report.
example.com._report._dmarc.<their domain> containing v=DMARC1.dig +short TXT example.com._report._dmarc.<their domain> returning v=DMARC1.This item cites no evidence id.
Engine output (verbatim)
no Content-Security-Policy to assess
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
`unsafe-inline` permits scripts written into the page — the very thing CSP exists to stop. `unsafe-eval` leaves the string-to-code path open. A policy carrying either is a header that exists without stopping an injected script.
script-src 'nonce-<value>', and repeat it as <script nonce="<value>">.unsafe-inline entirely, so keeping it for older browsers costs nothing.unsafe-eval, find and replace the library that calls eval or new Function.curl -sI https://example.com | grep -i content-security-policy and a browser console free of violation reports.This item cites no evidence id.
example.com in these instructions is a placeholder — read it as your own domain. It is not substituted automatically, because the same text also names real third-party hosts such as letsencrypt.org.
Engine output (verbatim)
1 certificates in the public logs, covering 2 names from 1 issuers
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Every certificate issued for your domain is published to the certificate transparency logs — which means an issuance you did not ask for appears there too. A name or an issuer you do not recognise means either the DNS was taken over, or someone inside obtained a certificate through a route nobody is tracking.
CT logs (crt.sh + Cert Spotter)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id crtsh:crtsh.certs:example.com
Engine output (verbatim)
none of the 15 variants checked is registered
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Accented Latin letters, and the digit zero against the letter o, render close enough to be indistinguishable on screen. A domain with one such substitution survives a visitor reading the URL carefully. Unlike a mistyped name, nothing about this is the visitor's fault.
dns-repsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-rep:dns.lookalike:example.com
Engine output (verbatim)
none of the 42 variants checked is registered
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A domain one character away is where a visitor in a hurry actually lands. A convincing sign-in page there collects credentials directly, and the same names appear as the sender of invoice fraud aimed at your customers. This item is not a defect in your domain; it reports what is around it.
dns-repsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-rep:dns.lookalike:example.com
Engine output (verbatim)
the certificates the server sends link up without a gap
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A server has to hand over enough intermediate certificates during the handshake for the client to reach a trusted root. When it does not, browsers that happen to hold that intermediate succeed and everything else fails. It does not reproduce on the developer's machine — it shows up as some visitors, some older devices, and a partner's integration failing.
ssl_certificate should point at — with Let's Encrypt, fullchain.pem, not cert.pem.SSLCertificateChainFile or an SSLCertificateFile assembled the same way.openssl s_client -connect example.com:443 -showcerts </dev/null lists the intermediate after the server certificate.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
1 valid certificates in CT logs
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
This verdict comes from the public CT indexes (crt.sh and Cert Spotter, merged). Under load an index answers with an empty list, and then the fact is not "no certificate" but "the index did not answer" (on 2026-09-08 a real, valid certificate went unfound this way). Only entries present with none valid is a failure; an empty index is reported as needing confirmation. With no valid certificate for the name people actually type, the browser interstitial becomes routine and users learn to click through it. An on-path attacker's forged certificate — or a plain-HTTP downgrade — then reads as the same familiar warning and gets accepted.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -ext subjectAltName.certbot --nginx -d example.com -d www.example.com, or add both names to the request at a commercial CA.nginx -t && systemctl reload nginx).openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -ext subjectAltName showing both names and a future notAfter.CT logs (crt.sh + Cert Spotter)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id crtsh:crtsh.certs:example.com
Engine output (verbatim)
newest certificate valid for 26510 more days
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An expired certificate makes every browser and API client refuse the connection, and the usual emergency response — turning certificate verification off at the client — hands an on-path attacker exactly the position they want. Renewal you have to remember is renewal that eventually gets missed.
systemctl list-timers | grep certbot) and prove the path with certbot renew --dry-run; with acme.sh, confirm acme.sh --cron --home ~/.acme.sh is in cron.--deploy-hook "systemctl reload nginx").openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -enddate sits well clear of that mark — automated renewal of a 90-day certificate normally leaves 30 days or more.CT logs (crt.sh + Cert Spotter)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id crtsh:crtsh.certs:example.com
Engine output (verbatim)
the certificate covers this host name
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
When the names in the certificate do not include the host being connected to, the browser stops on a warning page. The visitor either turns back or learns to click through warnings. Once that habit sets in, the warning for a real interception attempt gets the same click.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -text | grep -A1 'Subject Alternative Name'.certbot certonly -d example.com -d www.example.com.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
ECDSA key of 256 bits
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
The shorter the key, the more feasible it becomes to compute the private half. Whoever recovers it can impersonate the name in perfectly ordinary-looking traffic. RSA at 1024 bits is already in practical reach, and public CAs will not issue below 2048.
openssl genrsa -out key.pem 2048, or openssl ecparam -genkey -name prime256v1 -out key.pem for a curve, which is also cheaper per handshake.certbot certonly --key-type ecdsa -d example.com produces a curve key.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
the stapled status says the certificate is not revoked
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A revoked certificate was withdrawn because the private key leaked, or it was mis-issued, or one of those was suspected. Continuing to serve with a withdrawn key means anyone holding that key can impersonate you. Browsers commonly skip revocation checking when the check itself fails, so visitors see nothing.
TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
the certificate is issued by a separate authority
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A self-signed certificate is only its own word that it is correct — nothing outside it vouches for it. The browser warns, and visitors learn to proceed anyway. From then on, an attacker substituting a different self-signed certificate looks exactly the same to them.
certbot --nginx -d example.com or certbot --apache -d example.com obtains and installs one.openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
no internal-looking host names in the public certificates
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Every certificate is published to the certificate transparency logs when it is issued, and anyone can search them. Putting `staging.example.com` or `jenkins.example.com` in a public certificate hands out the shape of the internal estate as a list. To an attacker that is a map for choosing where to try.
https://crt.sh/?q=%25.example.com.CT logs (crt.sh + Cert Spotter)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id crtsh:crtsh.certs:example.com
Engine output (verbatim)
signed with SHA256-RSA
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
SHA-1 and MD5 have demonstrated collisions: two different contents that carry the same signature value. An attacker who can produce a second certificate the same signature accepts has stepped around the CA's guarantee entirely. Major browsers already refuse these signatures.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -text | grep 'Signature Algorithm'.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
the chain reaches a trusted root
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
If the chain does not reach a root the browser trusts, verification fails even when the certificate itself is perfectly legitimate. A missing intermediate is the usual cause. It shows up as "works in my browser, warns on some devices", which is exactly the shape of problem that goes unnoticed.
ssl_certificate at that combined file — with Let's Encrypt that is fullchain.pem, not cert.pem.SSLCertificateChainFile, or an SSLCertificateFile assembled the same way.openssl s_client -connect example.com:443 -servername example.com </dev/null reads Verify return code: 0 (ok).TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
all 2 name servers refuse a zone transfer
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A name server that transfers the zone to anyone hands over every record in one request — host names you never published, development environments, the names of internal systems, as a list. The attacker no longer has to guess what exists where.
allow-transfer { 203.0.113.53; }; on the zone or in options, with TSIG key authentication as well where you can.allow-axfr-ips.dig AXFR example.com @ns1.example.com returning Transfer failed.dns-authsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-auth:dns.authority:example.com
Engine output (verbatim)
the delegation matches the zone's NS records
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
When the name servers registered at the registrar differ from the NS records the zone itself publishes, queries reach different servers depending on the path. If the stale side still answers, it keeps returning pre-update content; if it has stopped, queries that land there fail. Either way it presents as "sometimes it does not work", which is hard to trace.
dig +short NS example.com agrees with dig +norecurse NS example.com @<a parent name server>.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
Engine output (verbatim)
name servers span 2 networks
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Name servers packed into one network all stop answering together when that network fails or is attacked. Once the name cannot be resolved, neither the website nor the mail is reachable. Adding more servers in the same place is not redundancy.
dig +short NS example.com and confirm the addresses sit in different networks.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
Engine output (verbatim)
2 name servers
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A single authoritative server is one outage away from the whole domain being unresolvable, and one compromise away from an attacker answering for every name you own — A, MX, and the ACME challenge used to issue certificates for you.
also-notify/allow-transfer on the primary, type secondary; on the other).dig +trace NS example.com — the NS set returned by the parent TLD's own servers — lists them all, and that dig SOA example.com @<ns> returns the same serial from each.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
Engine output (verbatim)
none of the 2 name servers resolves for strangers
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An authoritative name server that answers recursive queries from anyone becomes an amplifier for DNS reflection attacks: a small query producing a large answer, aimed at a third party whose address was forged as the source. The victim is someone else, but the traffic is recorded as coming from your server.
options, recursion no; and allow-recursion { none; };.dig @ns1.example.com example.org returning REFUSED.dns-authsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-auth:dns.authority:example.com
Engine output (verbatim)
SOA timers are within the usual range
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
The SOA timers set how often a secondary name server refetches the zone, and how long it keeps answering when it cannot. Too short an expire and a brief outage at the primary erases the whole zone. A retry longer than the refresh means the retry after a failure is slower than the ordinary update, which is backwards.
dig +short SOA example.com.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
Engine output (verbatim)
none of the 1 subdomains points at a claimable name
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Leaving a CNAME to a service you have cancelled means whoever registers that name next serves whatever they like on your subdomain. They can obtain a certificate for it too, so a fake page runs on your genuine domain behind a padlock. Neither the visitor nor the browser can tell.
https://crt.sh/?q=<the subdomain> for certificates issued in the meantime.dig +short <the subdomain> returns nothing.DNS answersubject api.example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-sub:dns.host:api.example.com
Engine output (verbatim)
an unregistered name does not resolve
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A zone with a wildcard answers names that do not exist. A mistyped name opens something plausible, so the visitor never learns they got it wrong. For an attacker it is a foothold: take a certificate for any name and stand up a convincing page on your domain.
* record and define the host names you actually serve.dig +short random-name-check.example.com, and getting nothing back.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
Engine output (verbatim)
the registration runs for another 26644 days
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
When a registration lapses, the website and the mail stop together. After a further grace period the domain becomes available to anyone, and certificates issued for it and mail received at it are then done in your name. Expiry is not a misconfiguration; it is a renewal someone forgot.
whois example.com.rdapsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id rdap:rdap.domain:example.com
Engine output (verbatim)
the registration carries the transfer and delete locks
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Without a transfer lock, whoever gets into the registrar account can move the domain to another registrar outright. Once the transfer completes, getting it back is extremely hard. Losing the domain means losing the website, the mail, and every certificate issued for the name.
clientTransferProhibited) and the delete lock (clientDeleteProhibited) in the registrar's control panel.whois example.com.rdapsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id rdap:rdap.domain:example.com
Engine output (verbatim)
no API specification is served at the checked paths
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An OpenAPI definition or a specification browser is a complete list of the operations available, their arguments and the shape of internal identifiers. Publishing one is often deliberate — but internal APIs and administrative operations frequently end up in the same definition. For an attacker it removes the work of enumerating what to try.
httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
The public index holds a version-qualified CPE for this host, which is only possible because the host named its own version. An attacker reads it and narrows straight to the known vulnerabilities for that release. This bites whether or not the build is actually patched: the index matches CVEs against the version it was told, so a patched host stays on every "vulnerable nginx" list built from it — and those lists are used as target lists.
server_tokens off; to the http block and run nginx -t && systemctl reload nginx.ServerTokens Prod and ServerSignature Off.smtpd_banner = $myhostname ESMTP.X-Powered-By.curl -sI https://example.com | grep -i '^server:' showing no version.This item cites no evidence id.
Engine output (verbatim)
no cross-domain policy file is served
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
`crossdomain.xml` configured Flash and Silverlight, both of which are gone. With `domain="*"` it let any site make credentialed requests against this domain in the implementations that read it. Browsers no longer do — but the file still being there means a policy from that era was never revisited.
crossdomain.xml and clientaccesspolicy.xml.domain="*" with the specific domains.curl -sI https://example.com/crossdomain.xml returning 404.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Redis, Memcached, Elasticsearch and MongoDB ship with no authentication: once reachable from the internet, anyone can read and write their contents. MySQL, PostgreSQL and SQL Server do authenticate, but exposed they are the first thing internet-wide scanners try credentials against. All of them were designed for a trusted network.
bind-address = 127.0.0.1 in MySQL's mysqld.cnf, listen_addresses = 'localhost' in postgresql.conf, bind 127.0.0.1 plus protected-mode yes in redis.conf, network.host: 127.0.0.1 in elasticsearch.yml, net.bindIp: 127.0.0.1 in mongod.conf.nmap -Pn -p 1433,3306,5432,6379,9200,11211,27017 <ip> reports nothing open, and from the application host that it still connects.This item cites no evidence id.
Engine output (verbatim)
the response is a configured site, not a stock page
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A server software's welcome page means nobody configured anything for that name. A forgotten virtual host stays on an old version because it is outside whatever gets updated. To an attacker it marks an entrance nobody is watching.
server_name _; and return 444;, and in Apache, the same treatment for the first VirtualHost.curl -sI https://example.com/ returns what you intended.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A Jenkins, GitLab, Grafana or Kibana console on the open internet is reconnaissance material by itself. Many allow anonymous viewing out of the box, and some — Jenkins above all — lead from running a job to running commands on the host. This check reads the product fingerprint a public index recorded, so moving the service off its default port does not hide it.
[auth.anonymous] enabled = false in grafana.ini).This item cites no evidence id.
Engine output (verbatim)
none of the checked directories lists its contents
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
With listings on, a directory without an index file shows the name of every file in it — working copies, material not yet published, administrative files whose purpose their name gives away. For an attacker it is a place to read the contents instead of guessing them.
autoindex off;.Indexes from that directory's Options, so Options -Indexes.curl -s https://example.com/uploads/ | head returning no listing.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
FTP and telnet carry credentials and content in the clear, so anyone on the path reads the username and password as they go by. TFTP has no authentication at all: knowing a filename is enough to fetch it. Encrypted replacements have been available for decades.
systemctl disable --now vsftpd, systemctl disable --now telnet.socket — and block the ports in the firewall as well.nmap -Pn -p 21,23 <ip> and nmap -Pn -sU -p 69 <ip> report nothing open.This item cites no evidence id.
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
The Docker API (2375, 2376), the Kubernetes API server (6443) and the kubelet (10250) all lead directly to running arbitrary containers on the host. Port 2375 in particular has neither encryption nor authentication, so anyone who can reach it has effectively root on that machine. This is how a whole platform is taken at once.
-H tcp:// from dockerd and listen on the Unix socket only; where remote access is genuinely needed, use 2376 with mutual TLS and restrict the source as well.--anonymous-auth=false.nmap -Pn -p 2375,2376,6443,10250 <ip> reports nothing open.This item cites no evidence id.
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Every additional listening service is another thing to patch and another version banner an attacker can match against an exploit. A long open-port list usually contains something nobody remembers deciding to expose.
ss -tulpn, and for each entry decide one of three things: switch it off (systemctl disable --now <unit>), bind it to loopback or an internal interface, or keep it public deliberately.ufw default deny incoming plus explicit allows, or a security group listing only the ports you named).nmap -Pn --top-ports 1000 <ip> against each host and check it comes back at 10 or fewer.This item cites no evidence id.
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
RDP and VNC reachable from the internet mean a constant stream of credential guessing. RDP has repeatedly carried pre-authentication remote code execution flaws, so exposure alone is dangerous; VNC can be configured to hand over the screen with no authentication at all.
ufw allow from 203.0.113.0/24 to any port 3389 proto tcp and then ufw deny 3389, checking ufw status numbered first for an unconditional allow that would win over it.nmap -Pn -p 3389,5900 <ip> returns filtered rather than open.This item cites no evidence id.
Engine output (verbatim)
none of the checked sensitive paths is served
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A readable `.git/config` often means the whole repository can be retrieved. A `.env` file contains database credentials and API keys as they are. Both get published by a deployment mistake, and attackers scan for them constantly. Once one has been read, the credentials in it have to be treated as handed over.
location ~ /\. { deny all; } in nginx, <FilesMatch "^\.">Require all denied</FilesMatch> in Apache.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
SMB was never meant to face the internet. Exposed, it offers share enumeration and credential guessing, and has carried widely exploited pre-authentication remote code execution flaws. It is one of the best-known entry points for ransomware.
nmap -Pn -p 139,445 <ip> reports nothing open.This item cites no evidence id.
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
SNMP v1 and v2c send their community string in the clear, and the default `public` is often still there. Read access alone hands over running processes, network layout and device models and versions — the reconnaissance stage, done for the attacker. Being UDP, it is also used to amplify spoofed traffic at third parties.
rocommunity lines from snmpd.conf and define users with createUser and rouser.public and private community strings in place.nmap -Pn -sU -p 161 <ip> does not report open.This item cites no evidence id.
Engine output (verbatim)
no issues across indexed hosts
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
These CVEs come from a public index matching the version you publish in your own banner against a CVE database. That method cannot see distribution backports: Ubuntu and Debian apply the fix and leave the upstream version number alone, so a patched host and an unpatched one are the same string from outside. Measured on a real host — nginx 1.24.0-2ubuntu7.17 carries the CVE-2025-23419 and CVE-2023-44487 patches and was listed for both anyway. That is not a reason to ignore the list: the same index is used as a target list, and CVEs well known enough to be indexed usually have working exploit code.
dpkg -l <package> and check for the CVE in the packaging changelog: zcat /usr/share/doc/<package>/changelog.Debian.gz | grep CVE-XXXX-NNNNN, then check that the release carrying the patch is at or below your installed version.rpm -q --changelog <package> | grep CVE-XXXX-NNNNN.apt update && apt upgrade or dnf upgrade followed by a service restart; for containers, bump the image and redeploy).This item cites no evidence id.
Engine output (verbatim)
certificate lifetime 90 days
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A one-year certificate is a year in which a stolen private key stays usable, because revocation is unreliable in practice and lifetime is the real limit. The CA/Browser Forum is also stepping maximum lifetimes down towards 47 days, and a manual renewal process that copes at one year will not.
--deploy-hook "systemctl reload nginx") and prove the unattended path with certbot renew --dry-run.openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates shows a notBefore-to-notAfter span of 90 days or less.CT logs (crt.sh + Cert Spotter)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id crtsh:crtsh.certs:example.com
Engine output (verbatim)
hybrid post-quantum key exchange accepted
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Traffic recorded today can be decrypted in bulk once a quantum computer can break the elliptic-curve key exchange protecting it — harvest now, decrypt later. A hybrid key exchange (X25519MLKEM768) removes the value of storing it, without weakening anything today.
X25519MLKEM768 by default.ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1; — check support first with openssl version, because an older OpenSSL refuses to start on an unknown curve.openssl s_client -connect example.com:443 -groups X25519MLKEM768 </dev/null completes and reports Negotiated TLS1.3 group: X25519MLKEM768.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
all prefixes RPKI valid
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
With no ROA, anyone who can speak BGP may announce your address space and pull your traffic to themselves — and once there, answer an ACME HTTP challenge and obtain a genuine certificate for your domain. Networks that drop RPKI-invalid routes reject such an announcement.
RIPEstat (RPKI)subject 192.0.2.1collected 01/09/2026 09:00 GMT+9
evidence id rpki:rpki.prefix:192.0.2.1
Engine output (verbatim)
no credential recognised in the 1 scripts read
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A script served to browsers is readable in full by everyone who loads the page. An API key or a private key in it is published. Obfuscation and minification do not change that. It does not stop being valid when you delete it; it was handed over when it was read.
httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.scripts:example.com
Engine output (verbatim)
robots.txt names no sensitive-looking path
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
`robots.txt` is a file anyone can read. `Disallow: /admin/` in it is an instruction about search results, not an access control — what it actually does is state where the administrative area is. It is one of the first files an attacker reads.
robots.txt.X-Robots-Tag: noindex with it or put <meta name="robots" content="noindex"> on it: both reach only a search engine that already fetched the page, rather than publishing a list.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
security.txt found
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
With no stated contact, someone who finds a flaw in your service has to guess an address; reports commonly go nowhere, and the finder either drops it or publishes it. One published contact is the difference between hearing about it first and reading about it.
https://example.com/.well-known/security.txt with at least Contact: mailto:security@example.com and Expires: (an RFC 3339 timestamp within a year), plus Preferred-Languages: and a Policy: line if you have one.Content-Type: text/plain; charset=utf-8, and diarise refreshing Expires — an expired file counts as invalid.curl -sI https://example.com/.well-known/security.txt returning 200 and text/plain.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.security_txt:example.com
Engine output (verbatim)
the page advertises no source map
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A source map relates minified script back to the code it was built from. Published with `sourcesContent`, it hands over that pre-minification code itself — variable names, comments, unreleased features, how the internal APIs are called. Everything from development, readable by anyone.
sourcesContent.devtool: false; in Vite, build.sourcemap: false..map) and relate them locally when you need to.sourceMappingURL and getting a 404.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
DMARC pct absent, so the policy applies to all mail
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
`pct` sets the share of mail the DMARC policy is applied to. At `pct=20`, four out of five forged messages fall outside the policy and reach the inbox even with `p=reject` published. That is a reasonable setting during a staged rollout, but left in place it means the domain is far less protected than the record appears to say.
pct from the _dmarc TXT record, or set pct=100 — 100 is the default when the tag is absent.dig +short TXT _dmarc.example.com showing no pct or pct=100, and watch the next report for legitimate senders that started being rejected.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
DMARC present
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
SPF and DKIM on their own tell a receiver nothing about what to do with mail that fails them, and give you no visibility. Without a DMARC record, someone can send invoice and password-reset mail as your domain and you will never learn it happened.
_dmarc.example.com in monitoring mode first: v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1 (in the zone, the host name is _dmarc).dig +short TXT _dmarc.example.com returning the record.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
DMARC rua present
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
With no `rua` address you receive no aggregate reports at all, so you cannot see who is sending as your domain, cannot tell a spoofing campaign from a forgotten legitimate sender, and have no safe basis for tightening the policy.
rua=mailto:dmarc@example.com to the _dmarc.example.com TXT record, keeping the existing v= and p= — for example v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; fo=1.example.com._report._dmarc.<other-domain> with v=DMARC1 or the reports are refused.dig +short TXT _dmarc.example.com showing rua=, and by receiving a report within a day or two.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
DMARC enforces on subdomains (subdomains inherit p=quarantine)
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An attacker does not need to forge the apex. A sender address at a subdomain that never existed — `billing.example.com` — reads to the recipient as the same organisation. With no `sp` and a permissive `p`, that route is unprotected.
sp=reject to the _dmarc TXT record.dig +short TXT _dmarc.example.com showing sp=reject, and by test-sending from a subdomain that does not exist and seeing it rejected.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
MTA-STS declared
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
SMTP still delivers in cleartext when STARTTLS is absent or the certificate does not verify, so an on-path attacker can strip the encryption and read or alter your mail. MTA-STS is the declaration that makes senders refuse that downgrade — and without the DNS record, senders never go looking for the policy.
_mta-sts.example.com reading v=STSv1; id=20260905000000.id is an arbitrary version string you must change whenever the policy changes, or senders keep using their cached copy.https://mta-sts.example.com/.well-known/mta-sts.txt has to exist too.dig +short TXT _mta-sts.example.com.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
every MX host has forward-confirmed reverse DNS
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Most receivers decide whether a sending host looks legitimate by checking that the address's reverse DNS resolves back to that same address. A sender that does not match is treated as spam or refused at connection time — before SPF and DKIM, however well configured, get a chance to matter.
dig +short -x <IP> returning a name, and dig +short <that name> returning the original address.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
all 1 mail exchangers offer STARTTLS
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Mail to an exchanger that does not offer STARTTLS crosses the network in the clear — subject, body and attachments readable at every hop. That covers the invoice a supplier sent and the password-reset notice alike. The sending side cannot demand encryption; its only choice is to send in the clear or not send.
smtpd_tls_security_level = may in main.cf alongside smtpd_tls_cert_file and smtpd_tls_key_file.tls_certificate and tls_privatekey.openssl s_client -starttls smtp -connect mail.example.com:25 completing the handshake.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
smtpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id smtp:smtp.mx:example.com
Engine output (verbatim)
all 1 exchangers present a valid certificate
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
STARTTLS with a certificate whose name does not match, or that has expired, or that reaches no trusted authority, leaves the sender unable to establish who answered. Most senders deliver anyway. The traffic is encrypted, but an attacker interposing on the path goes unnoticed, which is most of what the encryption was for.
dig +short MX example.com returns — and install it on the SMTP service.openssl s_client -starttls smtp -connect mail.example.com:25 reports Verify return code: 0.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
smtpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id smtp:smtp.mx:example.com
Engine output (verbatim)
SPF costs 1 of the 10 permitted DNS lookups
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A receiver evaluating SPF is permitted ten DNS lookups (RFC 7208 §4.6.4). Past that it abandons the evaluation, and SPF does nothing whatever the record says. Each sending service added brings another include, so records drift over the limit without anyone noticing.
ip4: addresses removes a lookup each.mail.example.com) and keep the apex record light.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
SPF uses no ptr mechanism
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
The ptr mechanism makes the receiver do a reverse lookup on the sending IP and then a forward lookup on whatever it returns. RFC 7208 §5.5 asks receivers not to use it and publishers not to publish it, because it is expensive and the answer is unreliable. A receiver that cannot resolve the reverse zone ignores the mechanism, which can leave a legitimate sender rejected.
ip4:203.0.113.10 and the like; a hosted service becomes the include: its documentation gives.dig +short TXT example.com | grep spf1 no longer shows ptr, and that legitimate senders still pass SPF in the next DMARC aggregate report.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
SPF present
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Without SPF, no receiver has any way to tell whether mail claiming to be from your domain actually left a server you use. Anyone can send invoices, password resets and bank-detail changes under your domain name, and they land in the inbox.
all — for example v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.10 -all.include:, a and mx must total 10 or fewer.dig +short TXT example.com | grep spf1 returns a single record, and that a test message to an external receiver shows spf=pass in its Authentication-Results header.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
exactly one SPF record
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
With two or more SPF records, a receiver does not pick one — it abandons SPF evaluation entirely (RFC 7208 §3.2, permerror). Each record can be perfectly correct and the domain still has no working sender authorisation. The usual cause is adding a new TXT record for a new sending system instead of extending the existing one.
dig +short TXT example.com | grep spf1.include:, ip4:, ip6:, a and mx term into a single record, dropping duplicates, and keep the strictest trailing all mechanism.dig returns exactly one line, and that legitimate senders go back to SPF pass in the next DMARC aggregate report.DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.host:example.com
DNS answersubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns:dns.mail:example.com
Engine output (verbatim)
the domain is on none of the 1 lists asked
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A listed domain name has its mail refused and its URLs stripped from other people's mail, whoever sends them. Unlike an address listing, changing where you send from does not avoid it. The usual causes are a compromised site redirecting visitors, or a wave of forged mail — and a listing follows even when you are the victim.
p=reject.dig +short example.com.dbl.spamhaus.org returns nothing.dns-repsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-rep:dns.reputation:example.com
Engine output (verbatim)
no address is listed on any of the 1 lists asked
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An address on a block list stops delivering mail. Many receivers consult the same lists, so the effect is not confined to one correspondent. The cause is nearly always at your end: a compromised machine inside, a misconfigured forwarder, a virtual server left running after it was cancelled.
https://check.spamhaus.org/).dns-repsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id dns-rep:dns.reputation:example.com
Engine output (verbatim)
all 1 external dependencies answer with a valid certificate
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An external resource the page loads that cannot be fetched means the features depending on it do not work. A certificate that does not verify makes the browser refuse the load outright. Providers shut down and move without notice, and nothing about that is visible from your side. Dependency domains have lapsed and been registered by someone else.
integrity attribute (web.sri) stops it executing if the provider's file is swapped.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.cdn:example.com
Engine output (verbatim)
the 1 recognised library versions are all at or above their advisory floor
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Older JavaScript libraries carry published vulnerabilities — typically, as in older jQuery, ones that allow script injection wherever user input is handled. The code runs in the visitor's browser with your site's privileges.
integrity attribute alongside it (web.sri).httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.scripts:example.com
Engine output (verbatim)
the page runs script from 1 external hosts: [cdn.example.net]
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Every script loaded from elsewhere runs on your page with your site's privileges. It can read what visitors type into forms and rewrite what they see. Advertising and analytics tags tend to be added by different teams at different times, and the full list is often something nobody holds.
script-src in the Content-Security-Policy to the list, so an unplanned addition stops rather than runs.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
all 1 external resources are fetched over HTTPS
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Fetching an external resource in the clear lets anyone on the path replace it. What they replace is code that runs on your page — to the visitor, something your site did. Before the question of whether the provider is trustworthy comes the question of whether the delivery is protected at all.
https://.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
no weak cipher suites
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
The suites this flags — RC4, 3DES, export grade, and anything without forward secrecy — can be broken or downgraded into with published attacks, letting an on-path attacker recover session data. Without forward secrecy, recorded sessions also become readable the day the server key leaks.
ssl_protocols TLSv1.2 TLSv1.3; with ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; and ssl_prefer_server_ciphers off;.SSLCipherSuite with SSLHonorCipherOrder off.nginx -t and reload.nmap --script ssl-enum-ciphers -p 443 example.com (or testssl.sh example.com) listing nothing outside that set.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
the negotiated suite has forward secrecy
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Without forward secrecy, the traffic can be decrypted from the server's private key alone. An attacker who records today's sessions and obtains that key years later can read every one of them. ECDHE derives a throwaway key per connection, so a key that leaks afterwards opens nothing that already happened.
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; with ssl_prefer_server_ciphers on;.SSLCipherSuite alongside SSLHonorCipherOrder on.openssl s_client -connect example.com:443 </dev/null 2>/dev/null | grep -i cipher showing an ECDHE or TLS 1.3 suite.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
the server selects no compression even when it is offered
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
With TLS compression on, the length of the encrypted traffic gives away its contents. In the attack known as CRIME, someone who can inject known text into the same connection and watch the length change recovers a cookie one character at a time. The cipher is not broken; compression is what makes the length carry information.
NoCompression to Options in openssl.cnf or disable it explicitly in the server's own configuration.openssl s_client -connect example.com:443 </dev/null 2>/dev/null | grep Compression reporting NONE.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
no obsolete TLS version accepted
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
TLS 1.0 and 1.1 have known cryptographic and implementation weaknesses that give an attacker a foothold for decrypting or tampering with traffic. Major browsers already refuse them, so leaving them enabled buys nothing.
ssl_protocols TLSv1.2 TLSv1.3; (drop TLSv1 and TLSv1.1).SSLProtocol -all +TLSv1.2 +TLSv1.3.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
the server states RFC 5746 secure renegotiation
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Renegotiation was originally specified with a flaw: an attacker who establishes a connection first, sends data of their choosing, and then splices the visitor's connection onto it, has the server receive a request the visitor never made. RFC 5746 adds an extension confirming that both halves are the same connection. A server that does not offer it either does not implement it or is running a version from before it existed.
openssl s_client -connect example.com:443 </dev/null 2>/dev/null | grep -i renegotiation reporting Secure Renegotiation IS supported.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
TLS 1.3 negotiated
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
TLS 1.3 removed the broken cipher suites from the specification outright and made forward secrecy mandatory in key exchange. A TLS 1.2-only configuration is not broken today, but it leaves room for a configuration mistake to cost real security. It also completes the handshake in one fewer round trip.
ssl_protocols TLSv1.2 TLSv1.3;.SSLProtocol -all +TLSv1.2 +TLSv1.3.openssl s_client -connect example.com:443 -tls1_3 </dev/null completes the handshake.TLS probe (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id tls:tls.probe:example.com
Engine output (verbatim)
every cookie states a SameSite policy
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
SameSite decides whether a cookie rides along on requests coming from other sites. With no attribute the default differs between browsers and has changed between versions. Cross-site request forgery — an attacker's page making the visitor's browser perform an action — is largely closed by this one attribute.
SameSite=Lax: sent on ordinary navigation, withheld on a cross-site POST.SameSite=None; Secure only for cookies genuinely embedded on other sites.session.cookie_samesite = "Lax".cookie: { sameSite: 'lax' }.config.action_dispatch.cookies_same_site_protection = :lax.curl -sI https://example.com | grep -i set-cookie showing SameSite on every line.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
every cookie is set with Secure
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A cookie without Secure is sent over plain HTTP too. Even on a site served only over HTTPS, making the browser fetch one image from `http://` on the same domain puts the session cookie on the wire. Anyone on the shared Wi-Fi or an intermediate hop can read it and become that user.
session.cookie_secure = 1 in php.ini.app.use(session({ cookie: { secure: true } })).config.force_ssl = true covers it.X-Forwarded-Proto and configure the app to trust it.curl -sI https://example.com | grep -i set-cookie showing Secure on every line.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
an arbitrary Origin is not granted access
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A server that returns whatever Origin it was sent lets any site the visitor opens read this site's responses. With credentials also allowed, what they read is the signed-in response. Opening an attacker's page in another tab is enough to carry away what should only appear on your screen.
Access-Control-Allow-Origin to a fixed value.Access-Control-Allow-Credentials: true only where credentials are genuinely needed, and note the wildcard cannot be used with it.curl -sI -H 'Origin: https://example.invalid' https://example.com/ | grep -i access-control and see that origin is not echoed back.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
the error page discloses no internals
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
An exception trace lists the framework and its version, absolute file paths, internal class and function names. A database error printed as-is gives away the table structure. To an attacker that is the information that decides what to try next. Detailed output enabled during development very often survives into production.
display_errors = Off in php.ini, DEBUG = False in Django, config.consider_all_requests_local = false in Rails, APP_DEBUG=false in Laravel.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
strict-transport-security present
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Without HSTS, the first request a visitor makes — typing the bare hostname, or following an old `http://` link — leaves in cleartext, and an attacker on that network can intercept it and keep the whole session on plain HTTP or their own TLS proxy. HSTS makes the browser refuse HTTP for your domain after one successful visit.
Strict-Transport-Security: max-age=31536000; includeSubDomains from the HTTPS listener (nginx: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; inside the server block listening on 443; Apache: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains").max-age=0, but only clients that return over HTTPS pick that up — anyone who never comes back keeps the old pin.max-age=300, confirm every subdomain has a working certificate, then raise it to a year.preload and submit to hstspreload.org only after that: removal from the preload list takes months.curl -sI https://example.com | grep -i strict-transport-security.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
HSTS meets the preload requirements
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
HSTS only takes effect after the browser has seen the header once. The very first visit still goes out over plain HTTP, and that one request is what an on-path attacker takes. Being on the preload list makes the browser force HTTPS from the first visit onward.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload from the apex.includeSubDomains covers every subdomain, so a single subdomain not served over HTTPS becomes unreachable — verify them all first.max-age for a while and confirm nothing breaks before submitting.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
HTTP redirects to HTTPS
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A site that answers on port 80 without redirecting lets an attacker keep a visitor on plain HTTP for the whole session — reading credentials and cookies and rewriting the page — while the user sees something that works perfectly normally.
server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://$host$request_uri; }.Redirect permanent / https://example.com/ or RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] inside <VirtualHost *:80>./.well-known/acme-challenge/ so it stays reachable over HTTP.curl -sI http://example.com returning 301 and an https:// Location:.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
no writing or diagnostic method is open
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
TRACE echoes the request back, which under the right conditions becomes a route for another script to read credentials. PUT, DELETE and the WebDAV methods allow files to be rewritten or removed when the configuration is wrong. None of them is needed to serve an ordinary website.
if ($request_method !~ ^(GET|HEAD|POST)$) { return 405; }.TraceEnable off and disable the WebDAV modules if you do not use them.curl -sI -X TRACE https://example.com/ returning 405 or 501.httpsubject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.probes:example.com
Engine output (verbatim)
every referenced resource is loaded over HTTPS
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
When an HTTPS page pulls in a resource over plain HTTP, that one request is unprotected — and an attacker on the path can swap the script and take the whole page. Browsers block mixed scripts and stylesheets by default, so it also shows up as the page simply breaking.
http:// to https://.Content-Security-Policy: upgrade-insecure-requests makes the browser rewrite them, but anything that genuinely has no HTTPS then fails to load — rewriting the references is the durable fix.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
no product version in the Server or X-Powered-By header
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A response header reading `nginx/1.24.0` lets an attacker narrow down what to try by matching it against a published vulnerability list. Hiding the version fixes nothing on its own, but it does take the host out of the set that indiscriminate scanning selects.
server_tokens off; in the http block of nginx.conf.ServerTokens Prod and ServerSignature Off.X-Powered-By, use expose_php = Off in php.ini, or app.disable('x-powered-by') in Express.curl -sI https://example.com | grep -iE 'server|x-powered-by' shows no version.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
every cross-origin script and stylesheet states an integrity hash
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
A script loaded from someone else runs on your page as your page. Providers have been compromised, and so have the networks that deliver their files. An integrity attribute makes the browser refuse to execute anything whose contents do not match the value you stated.
integrity="sha384-..." and crossorigin="anonymous" to external script and link elements.openssl dgst -sha384 -binary file.js | openssl base64 -A, though most providers publish it..../lib@1.2.3/lib.js) and make replacing the hash part of the upgrade procedure.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com
Engine output (verbatim)
X-Content-Type-Options is nosniff
Score gain: not computed
Subjects (1 in total, including any that were not inspected)
Risk detail
Without this header the browser does not trust the response's Content-Type and guesses from the content instead. A file a user uploaded can therefore be executed as script depending on what is inside it — which, on any site with uploads or user posts, is stored script execution.
X-Content-Type-Options: nosniff on every response.add_header X-Content-Type-Options "nosniff" always; to the http block and run nginx -t && systemctl reload nginx; in Apache use Header always set X-Content-Type-Options "nosniff".add_header inside a location block cancels every add_header from the server block, so repeat it in any such location.curl -sI https://example.com | grep -i x-content-type-options.HTTP response (active check)subject example.comcollected 01/09/2026 09:00 GMT+9
evidence id http:http.headers:example.com