Some notes on curating the set of CAs that Firefox trusts
In light of recent events involving WoSign (and there's more), I decided to distrust their CA certificates in my Firefox setup. This turned out to be much more involved than I expected, but also much more educational.
This is not the first time I've done this sort of thing, or more exactly this is not the first time I've tried to. And in that little remark is a tale. When I've done this in the past, the CAs that I told Firefox to 'Delete or distrust' in its certificate manager came back the next time I updated my custom Firefox build, and so for years I assumed that this was because Firefox kept this in a way that saw it overwritten on updates. This time around I decided to fix it in my source code, so that WoSign would be gone for good no matter what. While I had some initial success at this (or at least I seemed to), it didn't actually seem to make a different in my real Firefox. Never mind that I'd told my Firefox to delete WoSign and I'd theoretically stripped it out of my Firefox source code, there it was again in Firefox's list of known CAs and their certificates.
It turns out that I was wrong about what was happening, partly because I wasn't paying close enough attention and partly because Firefox has an extremely misleading and terrible UI for this. So let me tell you what's really going on. First, the CAs that I was trying to remove didn't just come back when I updated Firefox. They turn out to come back immediately, as in 'if you close the certificate manager and reopen it, your 'deleted' CAs are back'. The reason I thought the CAs came back when I updated Firefox was simply because that's generally what prompted me to check their status again. Second, although they were back (or never removed), Firefox at least in theory wasn't trusting them.
(It's at least very hard to reliably see the trust status of a CA cert in the certificate manager. It may be impossible unless you know a lot about NSS and what you're doing. And I never attempted to find test HTTPS sites for the CAs I was distrusting.)
Firefox (or more exactly NSS) has an internal collection of built in (root) CA certificates, and this collection can't be altered. When you tell Firefox to 'delete or distrust' such a certificate, what it actually does is copy that certificate to a certificate database in your Firefox profile and then marks it as 'do not trust this certificate'. The certificate database overrides the built in NSS database. So far, so good.
However, nothing in Firefox ever seems to clean up old certificates from your profile's certificate database. Even if NSS itself removes a CA certificate, your Firefox may still have it in the database and if it's there Firefox will show it in the big list of CAs and their certificates. When I explicitly distrusted WoSign through Firefox, of course it immediately got put into my profile's cert database and stayed there even though I really had taken it out of NSS. In fact my profile is rather old and it turns out that over the years, all sorts of CA certs had wound up in my profile's certificate database.
(Although I haven't tested this much, it seems that Firefox will copy CA certificates into your profile's certificate database under any number of circumstances, not just if you explicitly distrust them. I believe the certificate database may also be used to save or cache copies of intermediate certificates that Firefox has seen and validated.)
Since I've never added certificates to Firefox, only distrusted various ones, I wound up dealing with all of this by simply deleting the entire certificate database from my profile. So far this doesn't seem to have had any disastrous consequences (for example, my saved website logins and passwords are intact), and I'm happy to rely on the default state of NSS. Now that I know where this data is in the Firefox source, I can do my distrusting there.
(It turns out that Mozilla knows the certificate manager needs a lot of work (cf) but doesn't consider it a particularly high priority. I half disagree with them and half see where they're coming from.)
PS: Distrusting WoSign CA certificates is more involved than this, because at least some of WoSign's CA certs are cross-signed by StartComm, which WoSign now owns. Removing WoSign's CA certs from NSS doesn't prevent these cross-signed certificates from chaining back up to a valid CA certificate that NSS knows about and still trusts, and I'm not quite ready to distrust StartComm too (although maybe I should).
PPS: My overall conclusion is that this is a mess and I don't really understand it yet. I can do some things, but not enough.
Sidebar: The files involved and some other bits
The certificate database is probably called
cert8.db in your
profile. It can be examined with NSS's
certutil program, and as
far as I'm concerned it's best to make a copy of the live file in
another directory and point
certutil at your copy. If you do this,
you'll discover that
certutil also needs a copy of your profile's
In the certificate manager, I don't know what the difference is between a 'Builtin Object Token' and a 'Software Security Device'. Some CA certificates use one, some use others. Having peered at the code a little bit, it's possible that a 'Software Security Device' is a CA certificate that is in your profile's certificate database (either because you sneezed on it in the certificate manager or because it's an intermediate certificate that Firefox has seen and cached).
In the full Firefox source code, the NSS CA certificate data file
security/nss/lib/ckfw/builtins/certdata.txt. CA certificates
seem to have both a 'Certificate ...' and a 'Trust for ...' bit; I
took both out for the CA certs that I removed, just to be sure.
There may be a way to keep the certificate but explicitly tell
NSS to distrust it.