36

I have difficulty reaching various secure web sites. They give me a certificate expired error. They work on Firefox but not Safari or Chrome. They also work on newer versions of macOS (e.g. Catalina, Big Sur). This seems to be because Safari and Chrome use the OS root certificate store and Firefox uses its own, and El Capitan is not being updated.

From here there are:

  • Trusted certificates establish a chain of trust that verifies other certificates signed by the trusted roots — for example, to establish a secure connection to a web server. When IT administrators create Configuration Profiles, these trusted root certificates don't need to be included.
  • Always Ask certificates are untrusted but not blocked. When one of these certificates is used, you'll be prompted to choose whether or not to trust it.
  • Blocked certificates are believed to be compromised and will never be trusted.

There is a list of fingerprints of the current certificates there, but no downloadable bundles of certificates.

How do I update my root certificates on an older version of OS X 10.11

user3439894
  • 58,676
abligh
  • 1,031
  • Related: https://apple.stackexchange.com/questions/392599/addtrust-external-ca-root-certificate-expired – lhf Jun 14 '21 at 00:32

4 Answers4

54

The easiest way to do this is to transfer your System Root certificates from another Mac to which you have access that runs a more modern version of macOS. (Why not just download them? See note that the end of this answer.)

  1. First find the more modern Mac with a working set of System Root certificates (i.e. that can access the problematic web sites)
  2. On that Mac, launch Keychain Access, select "System Roots", select all the certificates, select File->Export, and export them as rootcerts.pem file. This file will contain all the certificates concatenated.
  3. Copy the rootcerts.pem file to your antique mac
  4. Make the trustroot shell script below, e.g. by copying it into a file, then using chmod 755 trustroot
  5. Run sudo ./trustroot rootcerts.pem
#!/bin/bash
DIR=${TMPDIR}/trustroot.$$
mkdir -p ${DIR}
trap "rm -rf ${DIR}" EXIT
cat "$1" | (cd $DIR && /usr/bin/split -p '-----BEGIN CERTIFICATE-----' - cert- )
for c in ${DIR}/cert-* ; do
   security -v add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" "$c"
done
rm -rf ${DIR}

What the script does is splits the .pem file into a number of certificates in the temporary directory concerned, then adds them as trustRoot certificates to the System key chain; they will then operate as trusted roots in addition to the certificates in the original "System Roots" keychain. In case you were wondering, you cannot add them to the System Roots keychain as that can only be updated by the operating system.

Note this copies over the first group of certificates ("Trusted Certificates" in the question), but not the second nor the third.

Kudos to this answer for a hint.


You might wonder why I didn't simply put a link to a more modern bundle of certificates somewhere on the web. After all, that would allow you to skip steps 1-3, and simply download rootcerts.pem. The answer is that you would have no way of knowing that I had not tampered with the root certificates and inserted one of my own, allowing me to impersonate any website by making a fake certificate signed with my own root certificate. Please therefore treat with extreme skepticism any advice to solve this problem by downloading root certificates from anywhere unless you can independently check the provenance of those certificates.

That said, if you have no other option, a reasonable place to download a certificate bundle would be from the curl web site here (untested), as most people trust curl.

eSavior
  • 25
abligh
  • 1,031
  • Im getting this error when following your guide Error reading file /cert-* – TheCrazyProfessor Oct 01 '21 at 14:06
  • @TheCrazyProfessor - That's odd. Assuming you copied the script exactly, that would imply DIR is not being set. Can you insert a line above for c ... saying echo DIR is '"'$DIR'"' and see if you get something like DIR is "/var/folders/_r/[something]/T/trustroot.[something]"- if not check TMPDIR is set to something first (e.g. do export TMPDIR=/tmp before running the script) – abligh Oct 01 '21 at 17:30
  • Got this: DIR is "" Not sure if you mean I shall write export TMPDIR=/tmp in the console or in the script but anyways I tried both. No result there... Is there a specific folder I need to run the script from? – TheCrazyProfessor Oct 01 '21 at 18:52
  • @TheCrazyProfessor should not need to be in a specific folder. Either place should work. I know this sounds odd, but can you check the second line of the script starting DIR= has been copied correctly (and indeed the first line). That sets the bash env variable DIR to something (even if TMPDIR is empty, DIR should at lest have trustroot. in it), and the echo command seems to show it is empty a few lines later. Inserting spaces (for instance) will break things. – abligh Oct 01 '21 at 19:01
  • 1
    Found out the issue, my dad forgot to enter the first line... (THANKS DAD) Anyway thanks for the help :D – TheCrazyProfessor Oct 01 '21 at 19:14
  • 2
    This answer saved my bacon today. Worked like a charm. – Sherwood Botsford Oct 01 '21 at 23:39
  • 2
    You saved my mom's night. Thank you – Hammerbot Oct 02 '21 at 08:45
  • Hm, I'm not famliar with the shell, however I think I was sticking to the script. Nevertheless I got the shells response No such file or directory whilst trying to set the chmod 755 for the script file. I definitely am in the right directory as with ls showed all files in there correctly. Stephans-Mac-Pro:certificates admin$ ls rootcerts.pem trustroot.sh I'm logged in as admin as well. Any idea what I did wrong? Thx – stephana Oct 18 '21 at 11:56
  • 1
    @stephana A typo maybe. Type chmod 755 followed by a space followed by t, then press TAB to have it auto-complete the name. – nohillside Oct 18 '21 at 12:16
  • 1
    this worked perfectly to update a system running MacOS 10.11.6 from a system running MacOS 10.15.7!!! Thanks!! – TimmyG Oct 23 '21 at 18:53
  • This would be really great if someone could put up the .pem file containing those latest certificates! I doubt quite strongly that this would run afoul of any Apple proprietary whatever - in fact, the certificate at cause is available freely (see my separate answer). – RJVB Oct 29 '21 at 11:15
  • 1
    @RJVB I deliberately did not do that, as you would have no way of knowing that those certificates were genuine. I could sneak in another certificate all of my own allowing me to impersonate any web site for anyone who downloaded my bundle. I will update the answer to say why I did not do that. – abligh Oct 30 '21 at 06:03
  • I get your argument but at some point you have to assign trust, I think that's the whole point here. We also trust Apple not to insert things (not just certificates) that allow them to do who knows what with our private data. – RJVB Oct 31 '21 at 09:42
  • Also, why only copy the 1st group of certificates instead of all of them? If you export a n up-to-date System Roots and that can only contain things added by the system, why would you not want to import all that content in complement of the contents of the System Roots on outdated system? – RJVB Oct 31 '21 at 10:05
  • 1
    @RJVB given the readers of this question have already purchased something from Apple who supplied their original cert bundle, I think it's more likely that they trust Apple than a random guy on the internet (me), as they did when they were updating their OS (before Apple stopped supplying updates). I'm not sure I understand your second point: I am deliberately only copying the OS supplied certificate bundle and not (e.g.) user supplied certificates, for the same reason. – abligh Oct 31 '21 at 10:13
  • From what you indicate in your answer, and from what I've seen myself, the System Roots store can only be updated by the system. It can't thus contain user-supplied certificates. If it can, what guarantee is there that no user changed (increased) the trust level of any non-original certificate? FWIW, this store does correspond to a file in /System/Library/Keychains on my 10.9 system, so I PRESUME it is this file that is replaced periodically by Apple updaters. If so it should be possible to obtain it from said updaters, maybe even programmatically. – RJVB Oct 31 '21 at 10:21
  • @RJVB my apologies. I thought you were advocating exporting stores other than System Roots; I agree this cannot contain user-supplied certificates. Could you clarify what are you are advocating exporting in addition to what I currently export (which I believe is the whole of System Roots)? IE what did you mean by "why only copy the 1st group of certificates instead of all of them" - I believe what I suggested does copy all the certificates in System Roots. – abligh Oct 31 '21 at 11:06
  • I wasn't advocating, I was in fact asking what you (think you) are excluding with your instructions! In other words, can't you just export the whole of System Roots on the newer system to a .pem file, and then drag that file in/onto the System store opened with the Keychain utility on the target system? Looking again at the script, I don't actually see how it excludes any kind of certificate from the exported file, so I'm (still) at a loss what would be in but not the second nor the third [group]. – RJVB Nov 01 '21 at 12:22
  • Do you know how Apple ships the updates to the System Root, by including an updated version of the corresponding file in /System/Library/Keychain I presume? What's the latest update that did this? If the file in question can be extracted, all one would need to do is provide up-to-date info about the latest installer(s), and a recipe how to extract and install the file. – RJVB Nov 01 '21 at 14:02
  • but not the second nor the third [group] refers to the second or third groups in the question, i.e. "Always Ask" and "Blocked". I checked empirically no blocked ones were exported. I have no always ask ones. I don't know precisely how the system keychain is (re)built on OS updates. A command line way of extracting it would be more satisfying than using keychain access, I agree. – abligh Nov 02 '21 at 00:39
  • 1
    Superb - I got my Dad's old Mac running El Capitan up and running again with my Montery certs using this approach. Thanks! – Mike Nov 06 '21 at 10:31
  • 1
    Thank you! The explanation is very clear. The steps are also clear and straight-forward. The script strikes a nice balance of being idiomatic but simple. AND it worked flawlessly. – John Ryan Jan 02 '22 at 18:29
  • 1
    This is horrible if Apple makes us do this. – mathtick Jan 05 '22 at 21:55
  • Hmm... This didn't fix my Safari on MacOS X 10.6.8 Snow Leopard even though it makes all the sense in the world... Yes, the iMac I want to use really qualifies as "ancient" - and the reason for using it is that I'm trying to revive some old source code that won't build on the latest macOS. I got the certificates from Monterey. – Radu C Jan 16 '22 at 11:46
  • @RaduC From memory the script should print something for each certificate it imports. Did that happen? If not, check how you exported them. Try using Keychain Access to check the certificates have been imported correctly. Use Safari (click on the padlock in the location bar) to determine which are missing. The machine I used is snow leopard and similarly ancient (2013 MBP) so it should work. – abligh Jan 16 '22 at 16:55
  • @abligh Yes, it did print everything. I don't know what I should see in Keychain Access exactly, but all the certificates in System Roots expire in the future. As this is low-priority, I just installed Firefox 45.9.0 ESR, and I'm whitelisting sites that complain. The web is half-broken anyway, as not all JavaScript is able to run anymore. Anything protected by CloudFlare is out of the question (e.g. GitLab) – Radu C Jan 18 '22 at 14:43
  • It says not to comment with things like 'thanks' but I'm going to anyway... this hint has helped me solve this issue for so many friends with older macbooks, and helped with the many that keep and choose to use with legacy versions of OSX. So t h a n k y o u and p l u s o n e to you! – Andy D Jul 18 '22 at 12:53
  • 1
    cURL also maintains a list of root certificates that you can download and verify with a SHA256 hash, if you trust them. I think most people do! https://curl.se/docs/caextract.html – dotnetCarpenter Dec 09 '22 at 13:58
  • @dotnetCarpenter thanks - I added a para. – abligh Dec 09 '22 at 17:38
  • I'm working on this problem with an antique in early 2023 and having no luck with this, or the x1.i.lencr.org solution. Funny enough, it's discussions.apple.com still refuses to load. Most others seem ok. – Nilloc Feb 07 '23 at 19:15
  • I'm attempting to run this within 10.3 on my old iMac G4 but Terminal/Darwin's version of "split" doesn't have the patterns -p command. Also, security doesn't have the add-trusted-cert command. I could split the certs on a modern machine then move them over, but what can I do instead of add-trusted-cert? Does 'add-certificates' do the same thing? – Michael Innes Mar 06 '23 at 22:49
  • Saved my bacon on 10.11.6 El Capitan. Fine work sir. – Eric Hanson Aug 08 '23 at 20:06
5

For anyone without access to an up-to-date Apple OS install: you can download the root certificate at cause (that one exclusively) from the issuer's site and install it. Instructions are here but double-check where in Keychain Access your system has stored the expired R3 certificate (could be "System Roots" instead of "System").

MacPorts have a port (apple-pki-bundle) which installs .pem file containing a bunch of certificates downloaded from Apple, GeoTrust and DigiCert (port source here. It does not at the moment include the ISRG certificate but I have to assume it contains at least a number of the certificates you'd get with the recipe outlined above. Checksumming ensures that you get the intended certificates; AFAICT you'll need to add the bundle to your system's root certificates yourself.

RJVB
  • 411
  • In order for this to be secure, you need to trust (some other way, i.e. not using their own root certificate) the website that you download the root certificate from. Also this will only update a single root certificate - the bundle has many tens of root certificates. – abligh Oct 30 '21 at 06:05
  • My answer does say that it's about the certificate which is causing probems at the moment. It is downloaded from the site of the organisation that issues it. I don't really see how you can do better - if a root certificate has to be signed by an independent entity it's no longer a root certificate AFAICT. – RJVB Oct 31 '21 at 09:39
4

Just tried these instructions on an old iMac Early 2009 with El Capitan (10.11.6)

Some operating systems hold onto the expired R3 > DST Root CA X3 chain even if your server is no longer using it. Try a restart of the affected client device.

For older macOS not updated by Apple:

  • Download the ISRG Root X1 certificate file from http://x1.i.lencr.org/
  • Open the Keychain Access app and drag that file into the System folder of that app.
  • Find the ISRG Root X1 certificate in System and double click on it, open the Trust menu and change "Use System Defaults" to "Always Trust", then close that and enter your password to confirm the change (if prompted).

everything becomes to work as expected.

nohillside
  • 100,768
0

Given answers didn't help for console applications. I believe most of them are curl-based, and here is what you can do:

  • make a backup for /etc/ssl/cert.pem file
  • open /etc/ssl/cert.pem with your favorite editor (sudo vim /etc/ssl/cert.pem, for example)
  • search for DST Root CA X3. If you found this (already expired) root cert - this is the root of the problem
  • delete this cert. All 42 lines of cert starting ### Digital Signature Trust Co. to -----END CERTIFICATE-----
  • check if it's ok now with curl --cert-status https://example.com command (replace domain with real one, ofc)

Why it helps. For compatibility reasons LE certs have two ways to root cert. For some reason(compatibility?) validation path with "DST Root CA X3" cert is preferred one. And, as far as I understood, curl is preferring its own set of root certs (instead of System ones) which are located at /etc/ssl/cert.pem. So removing stale root cert forces curl to use "ISRG Root X1"(if it's already there, ofc). NB! So, if you're doing it on a really old system you might have to do one more step - add this root cert to this file. Just be careful and get it from a trusted source.