Your Website's Security Certificate Isn't Trusted by Browsers

Your server is using a self-signed security certificate — one that you (or your server) created yourself, rather than one issued by a trusted authority. Browsers treat this the same way they'd treat a badge someone printed at home: it might look official, but there's no independent body vouching for it. Visitors to your site will see a security warning, and some browsers may block access entirely.

Business Impact And Actions

high urgency

Business Impact

Visitors who see a browser security warning are likely to leave immediately, damaging customer trust and conversion rates. If your business handles payments or personal data, self-signed certificates can trigger compliance failures under standards like PCI DSS, which explicitly prohibit them for sensitive data. It also makes it harder for your team and customers to detect if someone is intercepting their connection to your site.

What To Do

  1. Ask your developer to replace the self-signed certificate with a free, trusted one from Let's Encrypt — this is a straightforward task that typically takes under an hour.
  2. If you use a hosting platform (e.g. AWS, Cloudflare, Heroku, Netlify), check whether it offers one-click SSL — most modern platforms provide this at no extra cost.
  3. Once replaced, ask your developer to set up automatic certificate renewal so it never expires silently.
  4. If this certificate is on an internal tool only used by your own team, ask your IT contact whether it can be replaced or whether staff need to be warned not to click through certificate warnings.

Self-Signed TLS Certificate Detected — Missing CA Trust Chain

medium severity CVSS 5.3-6.5

Vulnerability Explanation

The server is presenting a TLS certificate that was signed by its own private key rather than by a trusted Certificate Authority (CA). Browsers and API clients maintain a built-in list of trusted root CAs; because a self-signed certificate does not chain to any of these roots, clients cannot cryptographically verify the server's identity. This negates a core purpose of TLS: endpoint authentication. Without it, a network-positioned attacker can present their own self-signed certificate during a connection, and the client has no reliable mechanism to distinguish the legitimate server from the impostor — enabling man-in-the-middle (MITM) interception. Additionally, self-signed certificates cannot be revoked through standard mechanisms (OCSP/CRL), meaning a compromised certificate has no kill switch.

Root Cause

A self-signed certificate was generated locally (e.g., via openssl req -x509 or a server's auto-generated cert) and deployed to production without obtaining a CA-issued certificate. This is common when a service is stood up quickly for testing and the certificate is never replaced before going live.

Technical Impact

A network-positioned attacker can perform a MITM attack by presenting their own certificate in place of the server's. Because there is no trusted CA to validate against, clients that bypass the browser warning (or API clients with certificate validation disabled) will encrypt traffic to the attacker's key, allowing decryption of credentials, session tokens, and sensitive data in transit. The certificate also cannot be revoked if the private key is compromised.

Severity Justification

Exploitation requires a network-positioned attacker (e.g., same network segment, ARP/DNS poisoning, or rogue Wi-Fi). Modern browsers display prominent warnings that most users will not bypass, reducing real-world exploitability. However, API clients and internal tooling often disable certificate validation when self-signed certs are present, which significantly increases risk in those contexts.

Affected Components

  • Self-signed TLS certificate — all versions

Remediation Steps

  1. Obtain a free, trusted certificate from Let's Encrypt using Certbot. For Nginx: `sudo apt install certbot python3-certbot-nginx && sudo certbot --nginx -d yourdomain.com`. For Apache: `sudo apt install certbot python3-certbot-apache && sudo certbot --apache -d yourdomain.com`. Certbot will automatically configure the web server and set up HTTP→HTTPS redirects.
  2. If the server is not publicly accessible (internal service), set up a private internal CA and distribute its root certificate to all client trust stores, rather than using a self-signed cert. This preserves chain-of-trust validation.
  3. Enable automatic renewal. Certbot installs a systemd timer or cron job by default. Verify it with: `sudo certbot renew --dry-run`.
  4. After replacing the certificate, audit any API clients, CI/CD pipelines, or internal services that connect to this endpoint and remove any `verify=False`, `--insecure`, or `ssl_verify=false` flags that were added to work around the self-signed cert.
  5. Test the new certificate with Qualys SSL Labs: https://www.ssllabs.com/ssltest/

Verification Steps

  1. Run `curl -vI https://yourdomain.com 2>&1 | grep -E 'issuer|subject|SSL'` and confirm the issuer is Let's Encrypt or your chosen CA, not the server itself.
  2. Visit https://www.ssllabs.com/ssltest/ and enter your domain — a valid CA-issued cert should score A or higher with no trust errors.
  3. In a browser, navigate to the site and confirm the padlock icon appears without any warning interstitial.
  4. Check renewal is scheduled: `sudo systemctl status certbot.timer` (systemd) or `sudo crontab -l | grep certbot`.

Code Examples (nginx)

Vulnerable
# Nginx config pointing to a self-signed certificate
ssl_certificate     /etc/ssl/certs/self-signed.crt;
ssl_certificate_key /etc/ssl/private/self-signed.key;
Fixed
# Nginx config after Certbot replaces with Let's Encrypt certificate
ssl_certificate     /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
include             /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;

Best Practices

  • Never deploy self-signed certificates to production or any externally accessible service — use Let's Encrypt (free) or a commercial CA.
  • Automate certificate renewal and set up expiry monitoring alerts (e.g., via UptimeRobot, Datadog, or `certbot renew --dry-run` in CI) to prevent silent expiry.
  • Audit all services that connect to this endpoint and ensure certificate validation is never disabled in client code — `verify=False` in Python requests or `--insecure` in curl are red flags.
  • For internal services that cannot use a public CA, deploy a private internal CA and distribute its root certificate to client trust stores rather than using self-signed certificates.

Found this in your infrastructure?

VulWall scans for this and dozens of other issues automatically.

Scan Your Domain Free