← Back to Blog
troubleshooting

Fix NET::ERR_CERT_AUTHORITY_INVALID: Certificate Not Trusted (2026)

NET::ERR_CERT_AUTHORITY_INVALID means the browser cannot verify the authority that issued the certificate. This is different from an expired certificate (ERR_CERT_DATE_INVALID) — here, the certificate itself may be valid, but the browser can't trust the chain connecting it to a recognized root CA. Here's every cause and the fix for each.

🔒

Free SSL Checker

Diagnose ERR_CERT_AUTHORITY_INVALID and see the full chain.

Try It Free →
🔒
Your connection is not private
NET::ERR_CERT_AUTHORITY_INVALID
The server's certificate authority is not trusted. The site may be using a self-signed certificate, or an intermediate CA is missing from the chain.

Cause 1: Missing Intermediate Certificate (Most Common)

The most frequent cause. Your certificate was issued by an intermediate CA, but your server only sends the end-entity certificate — not the intermediate. Browsers may accept this on desktop (they cache intermediates) but mobile Safari and curl will fail.

# Diagnose: count how many certs your server sends: echo | openssl s_client -connect yourdomain.com:443 -showcerts 2>/dev/null \ | grep -c "BEGIN CERTIFICATE" # Should show 2 or 3 (end-entity + 1-2 intermediates) # If shows 1, you're missing the intermediate # Fix: include intermediate in your certificate bundle cat yourdomain.crt intermediate.crt > fullchain.crt # Apache — use fullchain file: SSLCertificateFile /etc/ssl/certs/fullchain.crt # Nginx — always use fullchain file: ssl_certificate /etc/ssl/certs/fullchain.crt; # Reload web server: sudo systemctl reload apache2 # or: nginx -s reload

Cause 2: Self-Signed Certificate

Self-signed certificates are not trusted by browsers because there's no CA to vouch for them. Only appropriate for local development or internal tools where you explicitly add an exception.

# Identify if cert is self-signed (issuer = subject): echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \ | openssl x509 -noout -issuer -subject # If issuer and subject are identical → self-signed # Fix for production: get a real certificate from Let's Encrypt: sudo certbot --apache -d yourdomain.com -d www.yourdomain.com # Fix for local development: use mkcert to create a locally-trusted cert: mkcert -install # installs local CA in system/browser trust stores mkcert localhost 127.0.0.1 ::1 # creates locally trusted cert

Cause 3: Certificate Chain in Wrong Order

The chain must be in order from end-entity to root: your cert first, then intermediate(s), then optionally root. If the order is reversed, the chain validation fails.

# Check the order of certificates in your bundle: openssl crl2pkcs7 -nocrl -certfile fullchain.crt \ | openssl pkcs7 -print_certs -noout # Correct order: # subject=CN=yourdomain.com ← end-entity first # subject=CN=Intermediate CA # subject=CN=Root CA ← root last (often omitted) # Wrong order (reversed): # subject=CN=Intermediate CA ← intermediate first (WRONG) # subject=CN=yourdomain.com # Fix: rebuild the bundle in correct order: cat yourdomain.crt intermediate.crt > fullchain.crt

Cause 4: Untrusted or Private CA

Some enterprise setups use internal certificate authorities not recognized by public browsers. Common in corporate intranets.

# Check which CA issued the certificate: echo | openssl s_client -connect yourdomain.com:443 2>/dev/null \ | openssl x509 -noout -issuer # issuer=CN=Internal-CA ← not publicly trusted # For internal/intranet use — distribute the CA certificate to clients: # Windows: certmgr.msc → Trusted Root Certification Authorities → Import # macOS: Keychain Access → System → Certificates → Import (set trust to Always Trust) # Linux: sudo cp internal-ca.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates # For public-facing sites: switch to a publicly trusted CA: sudo certbot --apache -d yourdomain.com

Cause 5: OpenSSL CA Bundle Out of Date

Server-to-server requests (curl, Python requests, Node.js) use the system CA bundle, not the browser trust store. An outdated CA bundle may not include newer root CAs.

# Check CA bundle version: openssl version -d # OPENSSLDIR: "/usr/lib/ssl" ← this is where the bundle is # Update CA certificates on Ubuntu/Debian: sudo apt update && sudo apt install --reinstall ca-certificates sudo update-ca-certificates # Test with verbose SSL to see chain verification: curl -vvv https://yourdomain.com 2>&1 | grep -E "verify|issuer|subject|OK|error"

Diagnosis: Full Chain Check with OpenSSL

$ openssl s_client -connect yourdomain.com:443 2>/dev/null | head -20
 
# BROKEN chain (only 1 cert, missing intermediate):
depth=0 CN=yourdomain.com
verify error:num=20:unable to get local issuer certificate
Verify return code: 20 (unable to get local issuer certificate)
 
# CORRECT chain (depth shows full path):
depth=2 C=US, O=DigiCert Inc, CN=DigiCert Global Root G2
verify return:1
depth=1 C=US, O=DigiCert Inc, CN=DigiCert TLS RSA SHA256 2020 CA1
verify return:1
depth=0 CN=yourdomain.com
verify return:1
Verify return code: 0 (ok)

Quick Diagnosis Checklist


Check your certificate chain with our SSL checker

Verify your complete certificate chain, intermediate certificates, and trust status in seconds.