[Fixed] NPM error self signed certificate in certificate chain

A common NPM error self signed certificate in certificate chain. This post will go over multiple ways to fix this!

Jan 14, 2023 | Read time 9 minutes

🔔 Table of contents

Introduction

A recent issue that I came across when doing a npm install on a package is the NPM error self signed certificate in certificate chain.

The error message was: npm ERR! Error: SSL Error: SELF_SIGNED_CERT_IN_CHAIN

This can lead to SSL cert chain hell! This post I will over a few steps that we can take to resolve this error.

To fix the “npm self signed certificate chain” error, you can try one of the following solutions

  1. Upgrade Node and NPM version or let NPM to use known registrars npm install npm -g --ca=null
  2. Use the command export NODE_TLS_REJECT_UNAUTHORIZED=0
  3. Configure npm to use a specific certificate file: npm config set cafile path/to/cacert.pem
  4. If you are behind a proxy, you may need to configure npm to use it: npm config set proxy http://proxy:port
  5. Use the strict-ssl flag: npm config set strict-ssl false or npm install --strict-ssl false <package_name>

The full error looks something like the following:

npm ERR! Error: SSL Error: SELF_SIGNED_CERT_IN_CHAIN
npm ERR!     at ClientRequest.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/main.js:252:28)
npm ERR!     at ClientRequest.emit (events.js:67:17)
npm ERR!     at HTTPParser.onIncoming (http.js:1261:11)
npm ERR!     at HTTPParser.onHeadersComplete (http.js:102:31)
npm ERR!     at CleartextStream.ondata (http.js:1150:24)
npm ERR!     at CleartextStream._push (tls.js:375:27)
npm ERR!     at SecurePair.cycle (tls.js:734:20)
npm ERR!     at EncryptedStream.write (tls.js:130:13)
npm ERR!     at Socket.ondata (stream.js:38:26)
npm ERR!     at Socket.emit (events.js:67:17)
npm ERR! Report this *entire* log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! 
npm ERR! System Linux 2.6.38-13-generic
npm ERR! command "node" "/usr/bin/npm" "install" "jed"
npm ERR! node -v v0.6.12
npm ERR! npm -v 1.0.104

What does error SELF_SIGNED_CERT_IN_CHAIN mean?

When we come up with this error, it usually means that we are install a package from NPM that contains a self signed certificate. Self signed certificates in the certificate chain are not trusted by the system and therefore gives this error.

Sometimes the cause of this can be using a private NPM package repository, and that repo does not have the right SSL cert.

1. Upgrade Node and NPM version or let NPM to use known registrars!

One of the reason for this to occur is that with old versions of Node and NPM, they used a self signed certificate!

The npm client used a certificate authority (CA) file that was bundled into the client itself. This was previously necessary because the client used a self-signed SSL certificate.

However, NPM clients after Feb 2014 should not use self-signed SSL certificates anymore, so should not have this problem (https://blog.npmjs.org/post/78085451721/npms-self-signed-certificate-is-no-more).

To fix this issue, we need to update our NPM client.

Run the following to update your NPM client:

npm install npm -g --ca=null

Then additionally, run the following to set ther certificate authority:

npm config set ca=""

This just means to let NPM not use the bundled SSL that was not working.

If this does not work, upgrade to the latest version of node.js - since the latest stable version of node includes the NPM client that does not have this issue.

2. Use the command export NODE_TLS_REJECT_UNAUTHORIZED=0

We can set environment variable NODE_TLS_REJECT_UNAUTHORIZED to be zero:

Open up the terminal and run the following code (for Unix):

export NODE_TLS_REJECT_UNAUTHORIZED=0

For Windows, edit this environment variable in System Properties. You can also open up the command line and run:

set NODE_TLS_REJECT_UNAUTHORIZED=0

This variable just tells node to disable certificate verification - thus making your TLS or HTTPS connection insecure.

Although not ideal security wise, but if you want to get code working quickly and sure that your system is not exposed!

3. Configure npm to use a specific certificate file

If you trust the host, you can export the self signed SSL certificate and either:

  • tell NPM to trust our self signed SSL certificate as well, or
  • add it to your certificate store on your system and mark it as trusted.

Exporting the self signed SSL certificate

For example, we are using chrome and assuming the repo is https://registry.npmjs.org/ (this can be your own private self signed repo):

  1. Click on the padlock icon at the left
image of how to view ssl certificate
  1. Click on the “Connection is secure” link
  2. Click on “Certificate is valid” link
  3. Go to the details tab and hit export into a .cer or .crt file.
image of download the ssl certificate
  1. Combine all the certificates as-is into one .cer or .crt file.
  2. Put this file into a folder that you have access to. In my case I placed it in “C:\temp\trustedcert.cer”

Configure NPM to trust the exported self signed SSL certificate

After we have successfully export the cert, open up the command line and run the following to let NPM trust that cert:

npm config set cafile "C:\temp\trustedcert.cer"

Then we can run npm install without the SSL self signed cert issue.

Extending trusted certs

The command npm config set cafile <certfilepath>, tells npm to only use the certs provided in that file, instead of extending the existing ones with it.

We can set the environment variable NODE_EXTRA_CA_CERTS to extend pre-defined certs:

NODE_EXTRA_CA_CERTS to "<path to certificate file>"

4. If you are behind a proxy, check proxy settings

This issue can come up if we are behind a corporate proxy that wants to strip HTTPS.

Coporate proxies usually want to do this to “check for viruses” or whatever random reason :)

Image on how proxys work

Clear current proxy settings

Firstly, run the following commands to clear your current proxy settings:

npm config rm proxy

npm config rm https-proxy

Set new proxy settings

After we have cleared the existing proxy settings, we first need to make sure that we set the registry:

npm config set registry https://registry.npmjs.org/

Now set the new proxy settings with the following commands. Replace the proxyname with your corporate proxy URL.

npm config set proxy http://username:password@proxyname:8080

npm config set https-proxy http://username:password@proxyname:8080

Keep in mind that when you are using username and password, they need to be encoded. For example, if your password is: Welcome@12# then it will be like Welcome%4012%23.

Additionally, with your username, you may need to also include the domain name + username aswell.

For example, lets say we work at a company with domain BIGCORP and your username is johnnyweekend with password Welcome@12#, then your NPM proxy config might look something like this:

npm config set proxy http://bigcorp\\jonnyweekend:Welcome%4012%23@bigcorpproxy:8080

Tip: Check your corporate proxy settings and make sure that they are not blocking NPM registry

Check with your corporate network team that the proxy is not blocking the following URL: https://registry.npmjs.org

5. Use the strict-ssl flag

This is the last resort option and the above steps did not resolve your issue. We can use the strict-ssl and set it to false to tell NPM to not validate certificates.

This would mean that your TLS or HTTPS connections are not secure over NPM and risk of getting man in the middle attacks.

If you are sure about your system and ok to take that risk, we can run the following:

npm config set strict-ssl false

Summary

In this article, I went over the issue of NPM error of self signed cert in chain. This error is commonly due to the certificate chain containing a self signed certificate that is not trusted.

Usually this happens because we have a previous version of NPM or Node - in this case we need to upgrade to the latest version.

Another cause of this is due to NPM being behind a corporate proxy and not trusting the self signed cert. We can then update our proxy settings, download the certificates and tell NPM to trust it!

The last ditch effort to fix this is to use the strict-ssl flag and set it to false. This just tells npm to not validate certs and exposes us to TLS and HTTPS calls not being encrypted! However this will work if you are ok to accept the risks!

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube