ERR_CERT_AUTHORITY_INVALID: what it means and how to fix it

12 min readUpdated

NET::ERR_CERT_AUTHORITY_INVALID is the code Chrome shows when it cannot link a site's certificate to a root authority it trusts. Chromium's list of network errors describes it as a certificate "signed by an authority we don't trust" [1]. In our test, five different server setups produced this one code. A sixth, a missing intermediate certificate, did not show it in Chrome at all when the certificate gave the browser an address to fetch the intermediate from [13]. So the fix starts with finding out which setup it is. This page is about the Chrome code: Firefox names the same faults SEC_ERROR_UNKNOWN_ISSUER, and the codes for other failures are collected under SSL errors.

Quick facts

Browsers
Chrome and other browsers built on Chromium, such as Microsoft Edge [1] [11]
Exact text
Your connection is not private; the code NET::ERR_CERT_AUTHORITY_INVALID appears under Advanced [13]
Net error number
-202 in Chromium's list of network errors [1]
What failed
the path from the site's certificate to a trusted root: an intermediate is missing or wrong, or the root is not one the device trusts [13]
Firefox, same faults
SEC_ERROR_UNKNOWN_ISSUER, or MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT for a self-signed certificate [5] [13]
Who fixes it
the site owner, if other HTTPS sites open normally; the owner of the device or network, if every HTTPS site shows it [5]

What the error means

A browser trusts a site's certificate through a certificate chain. The site's certificate is signed by an intermediate authority, and the intermediate by a root. The server sends its own certificate and the intermediates; the root has to be among the root certificates the browser or the operating system already holds. ERR_CERT_AUTHORITY_INVALID means Chrome could not complete that path.

Chromium's comment on the code lists three ways it happens: an attacker has swapped in a certificate signed by an authority of their own, the operator has a certificate from an authority Chromium does not know, or the server presents a self-signed certificate [1]. Under Advanced, Chrome says the site "is using a security certificate that is not trusted by Chrome or your system configuration for web traffic encryption. This may be caused by a misconfiguration, or an attacker intercepting your connection." [2] [13]

What causes it: our test

We served each fault from a test server, with certificates from a test root of our own that both browsers were set to trust, and recorded what each browser showed [13]:

What causes it: our test
What the server sentChromeFirefox
its certificate and the intermediate (control)page loadedpage loaded
its certificate only, without the intermediateNET::ERR_CERT_AUTHORITY_INVALIDSEC_ERROR_UNKNOWN_ISSUER
its certificate only, which carried the intermediate's addresspage loadedSEC_ERROR_UNKNOWN_ISSUER
its certificate with an intermediate from another chainNET::ERR_CERT_AUTHORITY_INVALIDSEC_ERROR_UNKNOWN_ISSUER
a full chain to a root the browsers did not trustNET::ERR_CERT_AUTHORITY_INVALIDSEC_ERROR_UNKNOWN_ISSUER
the same chain with that root addedNET::ERR_CERT_AUTHORITY_INVALIDSEC_ERROR_UNKNOWN_ISSUER
a self-signed certificateNET::ERR_CERT_AUTHORITY_INVALIDMOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

Adding the untrusted root to what the server sent changed nothing in either browser [13]. A root counts only if the device already trusts it.

Antivirus or proxy software that inspects HTTPS, on a device where its root is not installed, is in the same position as the untrusted-root rows. When Chrome can name such software, it shows a separate screen. On a managed device, its explanation says a root certificate for that software "is required but isn’t installed"; on other devices, that the software "isn’t configured correctly". The applications it names are "antivirus, firewall, and web-filtering or proxy software" [2].

Why the site loads in one browser and fails in another

The third row is the split. The certificate carried the address of its intermediate in the Authority Information Access field (RFC 5280, section 4.2.2.1) [7]. Chrome downloaded the intermediate from that address and loaded the page; our test server logged one request from Chrome and none from Firefox [13]. Chromium's verifier has a component that retrieves issuers from these addresses [4]. Desktop Firefox instead preloads the intermediates that public authorities disclose, and our test authority is not among them, so a publicly trusted certificate may load in Firefox where ours failed [6].

What we did not see was a browser remembering an intermediate from an earlier connection. In a fresh session, each browser first opened the control server, which sent the intermediate, and then the server that left it out of the certificate chain: both still showed the error. After Chrome had fetched the intermediate for one server, a second server without the address failed too [13].

How to fix it

For site owners

Match the cause to a row of the table, then change what the server sends:

  • No intermediate. Serve your certificate followed by the intermediates. In nginx they go in the one file named by ssl_certificate, your certificate first; in Apache 2.4.8 and later, SSLCertificateFile can hold the intermediates as well, in order from your certificate towards the root [9].

  • The wrong intermediate. The intermediate has to be the one that signed your certificate: in our test, an intermediate from another chain gave the same error as none at all [13]. Install the chain that came with the current certificate, not a bundle kept from an earlier one.

  • A private or internal authority. Visitors' devices do not trust its root, and sending the root does not change that [13]. A public site needs a certificate from an authority browsers trust. For internal sites, the root has to be installed on every device that should trust it.

  • A self-signed certificate. The same applies: browsers have no root to check it against.

  • TLS ends at a load balancer, proxy or CDN. Check what that layer sends, not the server behind it.

After the change, check with curl or openssl s_client, as in the terminal check below, rather than from your browser: neither fetched a missing intermediate in our test [13].

For visitors

  • One site fails, others open. If Chrome shows Your connection is not private with this code on one site only, the fault is at the site, and only its owner can fix the certificate. In Firefox, the page for this fault says "there is nothing you can do to resolve it" [5]. Tell the owner the code.

  • Every HTTPS site fails. The cause is then on your device or network, not at the sites: software that inspects HTTPS without its root installed, as described above [2]. Firefox's advice is to turn off the antivirus feature that scans encrypted connections, "often called “web scanning” or “https scanning”", and, on a corporate network, to contact the IT department [5]. On a managed work device, ask the IT team, which installs the root certificate of its inspection software.

  • Try another network. If the sites open on mobile data and fail on the first network, the cause is on that network.

How to check the chain from a terminal

Unlike Chrome, curl and OpenSSL did not fetch the missing intermediate in our test, and curl lists that feature as not done [10] [13], so their output shows what the server sends:

$ openssl s_client -connect example.com:443 -servername example.com </dev/null
$ curl -sS https://example.com/ -o /dev/null

Output against our test servers, trusting only the test root [13]:

How to check the chain from a terminal
What the server sentopenssl s_clientcurl
its certificate only, with or without the intermediate's addressVerify return code: 21 (unable to verify the first certificate)(60) SSL certificate problem: unable to get local issuer certificate
an intermediate from another chain21 (unable to verify the first certificate)same as above
a full chain to an untrusted root20 (unable to get local issuer certificate)same as above
the same chain with the root added19 (self-signed certificate in certificate chain)self-signed certificate in certificate chain
a self-signed certificate18 (self-signed certificate)self-signed certificate

curl exited with code 60 in every row: a peer certificate that cannot be authenticated with known CA certificates [10]. The first three curl lines are the error covered on unable to get local issuer certificate. Under Certificate chain, s_client lists what was sent; a list that ends at your certificate, whose i: line names an intermediate, means it was not sent [13].

What the server log shows

The rejecting client also tells the server, with an alert. In our test, curl and openssl s_client -verify_return_error sent unknown_ca (48), and Chrome sent certificate_unknown (46) [13]. RFC 9846 defines unknown_ca as a chain that was received but whose CA certificate could not be located or could not be matched with a known trust anchor, and certificate_unknown as some other issue with the certificate (section 6.2) [8]. An OpenSSL server logs them as tlsv1 alert unknown ca and sslv3 alert certificate unknown [13]; reading alerts from both ends is covered on SSL handshake failed: causes and fixes.

When Chrome shows a different code

One fault in the chain gave a different code in our test [13]:

When Chrome shows a different code
What the server sentChromeFirefox
a full chain whose intermediate had expiredNET::ERR_CERT_DATE_INVALIDSEC_ERROR_EXPIRED_ISSUER_CERTIFICATE

An expired intermediate counts as a date problem, the code described on NET::ERR_CERT_DATE_INVALID [13]. When one certificate has several faults, Chrome reports the most serious: in Chromium's order, a revoked certificate comes before an untrusted authority, which comes before a wrong name and, further down, the dates [3]. So once the chain is fixed, a name or date fault on the same certificate can appear under its own code.

When the handshake fails for a reason other than the certificate, Chrome shows a different screen, "This site can’t provide a secure connection", with a code such as ERR_SSL_PROTOCOL_ERROR [1].

How to prevent it

Install the certificate and its chain in the same step, from the same delivery, and check the chain from outside after every certificate change. A bundle kept apart from the certificate can stop matching it, and our test showed that a mismatched intermediate fails like a missing one [13]. Automating issuance and installation removes the step where the chain is put together by hand.

Fix this with Bridge SSL

On Bridge CDN, TLS is terminated at the edge: there is no certificate file on your machine and no chain to assemble [12]. See what the platform includes at Bridge CDN.

FAQ

What does ERR_CERT_AUTHORITY_INVALID mean?

Chrome could not connect the site's certificate to a root authority it trusts. The server may have left out the intermediate certificate or sent the wrong one, or the certificate may come from an authority the device does not trust, including a self-signed one. [1] [13]

Why does the site work for some people and not others?

Browsers fill a missing intermediate in different ways. In our test, Chrome downloaded it from the address in the certificate and loaded the page, while Firefox showed SEC_ERROR_UNKNOWN_ISSUER. Desktop Firefox preloads the intermediates of public authorities, so the split depends on the certificate too. [6] [13]

Can I fix it as a visitor?

Only if the cause is on your side. If every HTTPS site shows the warning, antivirus HTTPS scanning or a proxy on your network is the place to look. If only one site does, the certificate is the site's to fix. [5]

Is it safe to continue anyway?

Chrome offers a link to proceed, marked unsafe. Its own explanation names both a misconfiguration and an attacker intercepting the connection as possible causes, and the screen cannot tell you which, so do not continue on a site where you sign in or pay. [2] [13]

Why do I see it on every site suddenly?

Something now sits between your browser and every site: security software that scans HTTPS, or a proxy on the network, whose root certificate is not installed on your device. [2] [13]

How do I check my chain is complete?

Run openssl s_client against the hostname and look at the certificate list and the Verify return code line. If the list holds only your own certificate, whose issuer line names an intermediate, the server does not send that intermediate. A check in your own browser can pass, because Chrome may fetch the intermediate itself. [13]

Sources

  1. Chromium, net/base/net_error_list.h (CERT_AUTHORITY_INVALID -202, CERT_DATE_INVALID, SSL_PROTOCOL_ERROR) and components/error_page_strings.grdp (error page headings).

  2. Chromium, components/ssl_errors_strings.grdp (IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS_V2) and components/security_interstitials_strings.grdp (IDS_MITM_SOFTWARE_EXPLANATION).

  3. Chromium, net/cert/cert_status_flags.cc (MapCertStatusToNetError).

  4. Chromium, net/cert/internal/cert_issuer_source_aia.h.

  5. Mozilla Firefox, toolkit/locales/en-US/toolkit/neterror/netError.ftl and nsserrors.ftl.

  6. Mozilla Security Blog, Preloading Intermediate CA Certificates into Firefox.

  7. IETF, RFC 5280, Internet X.509 Public Key Infrastructure Certificate and CRL Profile, section 4.2.2.1.

  8. IETF, RFC 9846, The Transport Layer Security (TLS) Protocol Version 1.3, section 6.2.

  9. nginx, Configuring HTTPS servers (SSL certificate chains); Apache HTTP Server 2.4, mod_ssl, SSLCertificateFile directive.

  10. OpenSSL 3.0, X509_STORE_CTX_get_error (verification error codes); curl, man page (exit code 60) and TODO (Authority Information Access).

  11. Microsoft Learn, Browsers and webview controls used by Office Add-ins (Microsoft Edge, Chromium-based).

  12. Bridge SSL, home page (What happens on my server?).

  13. Our test setup: Python HTTPS servers and an OpenSSL 3.0 server with certificates from a test authority of our own, Chrome and Firefox in headless mode, curl and OpenSSL 3.0 clients.