SSL Certificate Cannot Be Trusted (Nessus plugin 51192) means the scanner could not validate the chain from a TLS service’s certificate up to a certificate authority it trusts, usually because of a self-signed certificate, a missing intermediate, or a private CA. Fix it by serving a CA-issued certificate with its full chain and giving the scanner your internal root.
What the scanner is actually detecting
The scanner connects to a TLS service, collects the certificate chain the server sends, and tries to build a path from the server (leaf) certificate to a root in its own trust list. When that path cannot be built or checked, the finding fires. It is not limited to HTTPS on port 443: RDP, LDAPS, SMTP with STARTTLS, and management interfaces on switches or server BMCs trigger it too.
| Scanner | ID | Finding title |
|---|---|---|
| Nessus | Plugin 51192 | SSL Certificate Cannot Be Trusted |
| Qualys | QID 38173 | SSL Certificate – Signature Verification Failed Vulnerability |
| Rapid7 (InsightVM / Nexpose) | tls-untrusted-ca | Untrusted TLS/SSL server X.509 certificate |
Tenable documents three separate conditions behind plugin 51192, and the plugin output tells you which one you hit:
- Unknown issuer: the top of the chain the server sent does not descend from a known public CA. This covers self-signed certificates, private CAs the scanner does not know, and servers that omit an intermediate.
- Validity dates: a certificate somewhere in the chain is expired or not yet valid, including an intermediate you forgot about.
- Signature: a signature in the chain does not match the certificate (it must be re-signed by its issuer) or uses an algorithm the scanner cannot verify. A mismatched intermediate, such as an old or re-keyed one with the same name, produces the same result.
Hostname mismatch and self-signed certificates are reported as separate findings on the same port (Nessus 45411 “SSL Certificate with Wrong Hostname” and 57582 “SSL Self-Signed Certificate”), so expect them to appear together.
Real-world risk
Tenable rates plugin 51192 as Medium (CVSS v3 base score 6.5). The certificate itself is not an exploit. The problem is that a client cannot tell the real server from an impostor, so a man-in-the-middle can present its own certificate unnoticed. The bigger practical harm is behavioural: when admins click through warnings or scripts disable verification every day, nobody notices the day a certificate really is forged. On an isolated management VLAN the exposure is lower, but those are exactly the credentials an attacker wants.
How to confirm it on the host
Start with the scanner’s plugin output, which names the certificate that broke the chain. Then reproduce it with OpenSSL from a machine that has a normal trust store:
openssl s_client -connect host.example.com:443 -servername host.example.com -showcerts </dev/null
-showcerts prints every certificate exactly as the server sent it, in order. Check two things:
- Certificate chain: if the Certificate chain section lists only entry 0 (the leaf) and its issuer (
i:) is a public intermediate CA, the server is not sending the intermediate. - Verify return code:
0 (ok)means the chain validated. Common failures are20(unable to get local issuer certificate),21(unable to verify the first certificate),18and19(self-signed certificate, or self-signed certificate in the chain) and10(certificate has expired).
If the service uses your internal CA, test against that root explicitly. A clean result here plus a failing scan points at the scanner’s trust list, not the server:
openssl s_client -connect host.example.com:443 -servername host.example.com -CAfile corp-root.pem -verify_return_error </dev/null
To check a certificate bundle on disk before deploying it:
openssl x509 -in server.pem -noout -subject -issuer -dates
openssl verify -CAfile root.pem -untrusted intermediate.pem server.pem
How to fix it
Match the fix to the cause the plugin output reported:
| Cause | Fix |
|---|---|
| Intermediate not sent | Configure the server to send leaf plus intermediates |
| Self-signed or vendor default certificate | Replace with a certificate from a public CA or your enterprise CA |
| Internal CA unknown to the scanner | Upload the internal root to the scanner and distribute it to clients |
| Expired leaf or intermediate | Renew, and replace the stale intermediate in the bundle |
Apache httpd
Since Apache 2.4.8, SSLCertificateFile can hold the intermediates too, sorted from leaf to root, which makes SSLCertificateChainFile obsolete. Build the bundle with the server certificate first:
cat www.example.com.crt intermediate.crt > www.example.com-fullchain.pem
SSLCertificateFile /etc/ssl/certs/www.example.com-fullchain.pem
SSLCertificateKeyFile /etc/ssl/private/www.example.com.key
apachectl configtest only checks syntax, and at that stage mod_ssl only confirms that the certificate and key files exist. It does not load them, so a wrong order or a key mismatch passes the test, then makes the reload fail and the httpd parent process exit, which takes the site down. Before reloading, check the built bundle itself:
# the two outputs must be identical (x509 reads the first certificate in the file, so this also catches a wrong order)
openssl x509 -in www.example.com-fullchain.pem -noout -pubkey
openssl pkey -in www.example.com.key -pubout
# list the certificates in file order: leaf first, then the intermediate
openssl crl2pkcs7 -nocrl -certfile www.example.com-fullchain.pem | openssl pkcs7 -print_certs -noout
Back up the working files (see rollback below), then reload. On versions older than 2.4.8, keep the leaf in SSLCertificateFile and point SSLCertificateChainFile at the intermediate bundle.
nginx
nginx expects the leaf and its chain in one file, with the server certificate first:
cat www.example.com.crt bundle.crt > www.example.com.chained.crt
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/www.example.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/www.example.com.key;
}
If you use an ACME client such as certbot, point ssl_certificate at fullchain.pem, not cert.pem. Test with nginx -t before reloading.
IIS and other Windows (Schannel) services
IIS sends the chain that Windows can build from the local computer’s certificate stores. If the intermediate is missing there, only the leaf goes out. Import it into the Intermediate Certification Authorities store of the local computer:
certutil -addstore CA C:certsintermediate.cer
or with PowerShell:
Import-Certificate -FilePath C:certsintermediate.cer -CertStoreLocation Cert:LocalMachineCA
Then confirm the site’s https binding in IIS Manager (Site, Bindings, https, SSL certificate) points at the CA-issued certificate. If the served chain does not change, reboot the server in a maintenance window (iisreset alone does not refresh the HTTP.sys/Schannel chain cache). The same store import fixes other Schannel services that already use a CA-issued certificate.
If RDP presents its default self-signed certificate, importing an intermediate does nothing. Issue a Server Authentication certificate from your CA, place it in the computer’s Personal store, and bind it. Either set the GPO Computer ConfigurationAdministrative TemplatesWindows ComponentsRemote Desktop ServicesRemote Desktop Session HostSecurity > Server authentication certificate template, or set its thumbprint in Win32_TSGeneralSetting.SSLCertificateSHA1Hash (namespace rootcimv2TerminalServices).
Internal or enterprise CA (AD CS)
For internal systems, issue server certificates from your enterprise CA instead of relying on self-signed defaults. An enterprise root in AD CS is normally trusted by domain members automatically. For standalone or offline roots, distribute the root with Group Policy: Computer ConfigurationPoliciesWindows SettingsSecurity SettingsPublic Key Policies, right-click Trusted Root Certification Authorities, then Import.
On Linux clients, add the root to the system trust store:
# Debian / Ubuntu (PEM format, file must end in .crt)
cp corp-root.crt /usr/local/share/ca-certificates/
update-ca-certificates
# RHEL / Fedora
cp corp-root.pem /etc/pki/ca-trust/source/anchors/
update-ca-trust extract
Distro-packaged Java picks up the OS store after update-ca-trust / update-ca-certificates; applications that ship their own JRE need a separate keytool -importcert into that JRE’s cacerts.
Tell the scanner about your internal CA
If the chain validates against your internal root (as in the -CAfile test above), the remaining fix is on the scanner. Tenable’s guidance is to supply the root in PEM format, including the BEGIN and END CERTIFICATE lines:
- Nessus: Settings > Custom CA, paste the PEM certificate (several roots can go back to back), then Save.
- Tenable Vulnerability Management: in the scan, Settings > Advanced, paste into Trusted CAs.
- Tenable Security Center: put the PEM roots in
custom_CA.incand createcustom_feed_info.inc(below). Package both, log in as an Administrator (or Security Manager), click Username > Plugins > Upload Custom Plugins, select the .tar.gz and Submit; verify under System > System Logs.
Contents of custom_feed_info.inc (set PLUGIN_SET to the hour after your planned upload):
PLUGIN_SET = "201310161758";
PLUGIN_FEED = "Custom";
Then package both files:
tar -zcvf upload_this.tar.gz custom_feed_info.inc custom_CA.inc
Qualys and Rapid7 handle private CAs through their own settings, so check the vendor documentation for your product version.
How to verify the fix and rescan
- Rerun
openssl s_client -showcertsand confirm the chain now includes the intermediate and ends withVerify return code: 0 (ok). - For internal CAs, run the
-CAfile corp-root.pem -verify_return_errortest, which aborts the handshake if verification fails. - Confirm the custom CA is saved in the scanner before the rescan, not after.
- Run a targeted rescan of the affected host and port with the same policy that raised the finding, and check that plugin 51192 (or the Qualys or Rapid7 equivalent) no longer appears.
What can break and how to roll back
- Wrong order in the bundle or a mismatched key: nginx fails with
SSL_CTX_use_PrivateKey_file(...) failed (... key values mismatch)if an intermediate comes before the leaf, andnginx -tcatches this.apachectl configtestdoes NOT catch it, because it only checks that the files exist. Before reloading Apache, run the public key and bundle order checks from the Apache section above. - Pinned clients: API clients or appliances that pin the old certificate or its public key will fail after replacement. Inventory them before the change.
- Rollback: back up the current certificate, key and config before editing. On Apache and nginx, restore the files and reload. On IIS, the old certificate stays in the store, so you can rebind it in seconds.
Common false positive reasons
- The scanner does not know your internal root. Browsers on domain machines trust it; the scanner does not. Fix the scanner, not the server.
- Scanning by IP address. Without the right hostname, the server may return its default virtual host certificate, which is often self-signed.
- A TLS-inspecting proxy or load balancer between the scanner and the host presents its own certificate.
- An outdated plugin feed may lack a newer public root.
For a broader checklist, see our guide to why vulnerability scanners report false positives.
FAQ
Is “SSL Certificate Cannot Be Trusted” a critical vulnerability?
No. Tenable rates it Medium. It enables interception rather than direct compromise, but it deserves attention on anything that carries credentials.
Why does my browser show the site as secure while Nessus flags it?
Many browsers can fill in a missing intermediate on their own, from a cache or by downloading it. Scanners and most command-line clients only use what the server sends, so a missing intermediate still fails for them.
Can I fix it without buying a certificate?
Yes. Use a free ACME-based public CA for internet-facing services, or your enterprise CA for internal ones, and give the scanner your internal root.
Does uploading our internal CA to Nessus hide real problems?
No. It only adds that root as a trust anchor. Expired certificates, bad signatures and chains to unknown roots are still reported.
Tracking this finding across many hosts
Certificate findings tend to come back when certificates renew, so a TLS certificate inventory with owners and expiry dates helps stop the cycle. If you manage this at scale, SITEY is a self-hosted vulnerability management platform that imports findings from 16 scanners (Nessus results are imported by uploading a .nessus export). It merges duplicates per scanner, not across scanners, and per-finding retest is available for Nessus, Acunetix and Burp findings.
Sources
- Tenable: SSL Certificate Cannot Be Trusted (plugin 51192)
- Tenable: Resolving Plugin 51192
- Apache HTTP Server: mod_ssl documentation
- nginx: Configuring HTTPS servers
- Tenable Security Center: Upload Custom Plugins
- Microsoft Learn: Remote Desktop listener certificate configurations
- Microsoft Learn: Distribute certificates to client computers by using Group Policy