Fixing reused certificate issuer and serial in Firefox the proper way

Sometimes when deploying stuff in the lab with self-signed certificates I find myself quickly rebuilding VMs after making breaking changes. Normally that’s not a problem, except when Firefox is being used to access the rebuilt VM occasionally we might see this error:

Secure Connection Failed

An error occurred during a connection to 192.168.24.201. You are attempting to import a cert with the same issuer/serial as an existing cert, but that is not the same cert.

Error code: SEC_ERROR_REUSED_ISSUER_AND_SERIAL

The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.

Please contact the website owners to inform them of this problem.

I often see this occur with Foreman where the default configuration relies on the Puppet CA for certificate issuing.

In theory you should be able to fix this by heading to Settings -> Privacy & Security -> View Certificates, selecting the Servers tab and then deleting the offending entry. In practice, however, this doesn’t often work.

Some forum posts suggest removing the entire certificate database. This works, but it’s a bit heavy handed as it clears out any other exceptions you may have saved in the past.

To fix this properly we need to use certutil as included with the Mozilla NSS tools. This command shouldn’t be confused with certutil.exe included with Windows, which is completely unrelated!

In install certutil on Ubuntu we need the libnss3-tools package:

sudo apt install libnss3-tools

In macOS, I recommend using Homebrew or MacPorts to install the nss package e.g:

brew install nss

Quit Firefox if it’s running. In theory it’s possible to do this in-place with SQL NSS databases but I’ve found it a bit hit and miss in practice.

First we need to figure out the Firefox profile directory. The configuration for this is usually in ~/.mozilla/firefox/profiles.ini(Linux) or ~/Library/Application Support/Firefox/profiles.ini (Mac).

Identify the Path to your profile directory, in this case

[Profile0]
Name=default
IsRelative=1
Path=profiles/w6znk57b.default
Default=1

[General]
StartWithLastProfile=1
Version=2

So in this case my profile directory would be ~/.mozilla/firefox/profiles/w6znk57b.default in Linux or ~/Library/Application Support/Firefox/Profiles/w6znk57b.default on Mac. Yours may vary slightly – just note that the Path entry is relative to the location of profiles.ini so you need to include any subdirectories in your commands. Note that the path is case sensitive.

From here we can use certutil to list the certificates (-L) in this store to find the offending entry. Modern versions of Firefox use the SQL NSS database, so we need to provide the location of the database in the form of sql:path.

A tip here – it might be useful to use grep to filter for the common name of the certificate used by the page throwing the error.

certutil -d sql:$HOME/.mozilla/firefox/profiles/w6znk57b.default -L

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

DigiCert SHA2 Secure Server CA                               ,,   
DigiCert TLS RSA SHA256 2020 CA1                             ,,   
R3                                                           ,,   
Amazon                                                       ,,   
GTS CA 1O1                                                   ,,   
foreman1.lab.example                                         ,,   

In this case the foreman1.lab.example entry is the offending one that we want to remove. To get rid of it we use the certutil delete command (-D) and specify the certificate nickname listed above after the -n argument. I recommend putting quotes around the nickname in case it includes spaces.

certutil -d sql:$HOME/.mozilla/firefox/profiles/w6znk57b.default -Dn "foreman1.lab.example"

If certutil doesn’t return any messages then it’s likely to have worked. To verify we can simply run the list command again to check:

certutil -d sql:$HOME/.mozilla/firefox/profiles/w6znk57b.default -L
Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

DigiCert SHA2 Secure Server CA                               ,,   
DigiCert TLS RSA SHA256 2020 CA1                             ,,   
R3                                                           ,,   
Amazon                                                       ,,   
GTS CA 1O1                                                   ,,  

At this point you should be able to reload the offending site and it should now work (although you will likely be prompted to accept the certificate again!).

If the above steps don’t work, try closing Firefox and repeating the delete command without the sql: prefix.