A late contribution to the expired root in certificate chain issue… – Tales from the Crypto

A late contribution to the expired root in certificate chain issue…

In case you missed it, on May 30th, a root certificate expired.

This made a lot of applications very unreliable, and been widely regarded as a bad move.

Well, alright, what was regarded as a bad move is that applications should become unreliable in the specific circumstances involved here.

As short a TL;DR as I can manage

When you connect to a  server(web site or application) over SSL/TLS, the server has to send your client (browser or application) its Certificate.

In modern code, this Certificate is used by the client to trace back to a signing authority that is trusted by the client or its operating system.

Some servers like to help this process out, by sending a chain along with the Certificate for a couple of reasons:

  1. The client might not have the ability or time to go building and checking its Certificate chain, and choose to trust only servers that send it an entire chain they can trust
  2. Older clients might not be aware of the newer root certificates up to which the supplied Certificate chain connects.

This second situation is what we’re interested in here. A new root appears, new certificates are issued, and old clients refuse to honour them because they don’t have the new root in their trust store.

This is fixed with “cross-signing”, which allows an older, trusted root, to sign the new untrusted root, so that the older client sees a chain that includes the older root at the top, and is therefore trusted.

Older root certificates expire. It takes 20 years, but it finally happened at the end of May, to this one root certificate, “AddTrust External CA Root”

When that happens, a client who builds the certificate chain and uses this to trust the root certificate is happy, because it sees only certificates that it trusts.

A client who takes the certificate chain as supplied by the server, without building its own, will see that the chain ends in an expired certificate, and refuse to connect, because the entire chain cannot be trusted.

What do I bring to the party?

The two links I provided earlier are well worth a read if you’re interested in solving this problem, and really, I’ve got nothing to add to how this issue occurred, why it’s a problem, how to address it at your server, or any of those fun things.

What I do offer is a tool for .NET (Windows and Linux, Mac, etc) that lets you compare the certificate chain as presented by the server against the certificate chain built by a client. It will report if a certificate in either chain has expired. It’s written in C#, and built with Visual Studio, and takes one parameter – the site to which it will connect on port 443 to query for the certificate and chain.

It’s not a very smart tool, and it makes a few assumptions (though it’s relatively easy to fix if those assumptions turn out to be false).

But it has source code, and it runs on Windows, Linux and (presumably – haven’t tested) Mac.

How does it look?

Working against the sites listed at http://testsites.test.certificatetest.com/, we get the following results:

First: https://aaacertificateservices.test.certificatetest.com/ – Certificate issued from a CA signed by AAA Certificate Services root.


Interestingly, note that the certificate chain in the stream from the server doesn’t include the root certificate at all, but it’s present in the code where we ask the client code what certificates are in the chain for this server.

Second: https://addtrustexternalcaroot.test.certificatetest.com/ – Certificate issued from a CA signed by AddTrust External CA Root.


The certificates here expired on 5/30/2020, and it’s no surprise that we see this result in both the chain provided by the server and the chain provided by the client. Again, the root certificate isn’t actually in the chain from the server provided in the stream.

Third: https://addtrustaia.test.certificatetest.com/ – Certificate issued from a CA signed by USERTrust RSA Certification Authority with a cross cert via AIA from AddTrust External CA Root.


Nothing noteworthy here, but it’s included here for completeness. I don’t do anything in this code for an AIA cross cert.

Fourth, and most importantly: https://addtrustchain.test.certificatetest.com/ – Certificate issued from a CA signed by USERTrust RSA Certification Authority with a cross cert via server chain from AddTrust External CA Root.


Here’s the point of the tool – it’s able to tell you that there’s a certificate in the chain from the server that has expired, and may potentially be causing problems to visitors using an older browser or client library.

Enough waffle, where’s the chicken?

By now, you’ve had enough of reading and you want to see the code – or just run it. I’ve attached two files – one for the source code, the other for the executable content. I leave it up to others to tell you how to install dotnet core on your platform.

Here’s the source code

And here’s the binary

Let me know if, and how, you use this tool, and whether it achieves whatever goal you want from it.

Leave a Reply

Your email address will not be published. Required fields are marked *