How to fix Error: certificate verify failed (self-signed or expired SSL cert) in Node.js

Node.jsINTERMEDIATEHIGHUpdated Dec 9, 2025ยท 282 views

This error occurs when Node.js cannot verify the SSL/TLS certificate of a server you are trying to connect to. It typically happens with self-signed certificates, expired certificates, or missing intermediate certificates. The fix depends on whether you are in a development environment or production.

Quick fix

Fixes CERT_UNTRUSTED

# Check certificate details
openssl s_client -connect example.com:443 -showcerts

# Look for "Verify return code" in the output
# If it shows "self signed certificate" or "unable to verify", note the issuer
  1. Verify the certificate is intentionally self-signed or custom
  2. Use NODE_EXTRA_CA_CERTS environment variable (Recommended)
  3. Configure the ca option directly in your HTTPS requests
  4. Obtain and install the complete certificate chain
node.js โ€” error
# Check certificate details
openssl s_client -connect example.com:443 -showcerts
# Look for "Verify return code" in the output
# If it shows "self signed certificate" or "unable to verify", note the issuer
Error: certificate verify failed (self-signed or expired SSL cert)

What this error means

This error indicates that Node.js's built-in TLS/SSL verification has rejected a certificate during an HTTPS connection attempt. Node.js maintains a list of trusted Certificate Authorities (CAs) and validates all certificates against this list by default. When you encounter this error, it means the certificate presented by the server is either self-signed (not issued by a recognized CA), expired, or part of a certificate chain that cannot be traced back to a trusted root CA. This is Node.js protecting you from potentially insecure connections. While certificate errors often indicate legitimate security concerns, they can also occur in controlled environments where self-signed certificates are intentionally used, such as internal corporate networks, development/staging servers, private package registries, or internal APIs.

Typical symptoms

  • HTTPS requests fail with "certificate verify failed" error message
  • npm install commands fail when using a private registry or internal npm server
  • API calls to internal services return SSL certificate errors
  • Error message includes "CERT_UNTRUSTED" or "self signed certificate"
  • Application works correctly with HTTP but fails immediately with HTTPS
  • Code runs successfully on one machine but fails on another due to different CA trust stores
  • Docker containers cannot make HTTPS requests to internal services

Common causes

  1. Server is using a self-signed certificate not trusted by Node.js built-in CA list
  2. Missing intermediate certificates in the server certificate chain
  3. Corporate proxy or firewall intercepting HTTPS traffic with custom certificates
  4. Outdated Node.js version lacking support for modern or custom CA certificates
  5. Private npm registry, Docker registry, or internal API using custom CA certificates
  6. Certificate has expired or is not yet valid (future-dated certificate)
  7. System certificate store is missing required CA certificates for your environment
  8. Client connecting to different certificate than expected during development

How to fix "Error: certificate verify failed (self-signed or expired SSL cert)"

1Verify the certificate is intentionally self-signed or custom

Before bypassing certificate validation, confirm this is expected and not a security issue:

bash
# Check certificate details
openssl s_client -connect example.com:443 -showcerts

# Look for "Verify return code" in the output
# If it shows "self signed certificate" or "unable to verify", note the issuer

Check if you recognize the certificate authority. Only proceed with fixes if you trust the server.

2Use NODE_EXTRA_CA_CERTS environment variable (Recommended)

The most secure and production-ready solution is to add your custom CA certificate to Node.js's trusted certificate list:

bash
# Save your CA certificate to a file (e.g., ca-cert.pem)
# Then set the environment variable before running Node.js

export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
node your-app.js

Or add it to your start script in package.json:

json
{
  "scripts": {
    "start": "NODE_EXTRA_CA_CERTS=./certs/ca-cert.pem node app.js",
    "dev": "NODE_EXTRA_CA_CERTS=./certs/ca-cert.pem node --watch app.js"
  }
}

This method is safe because it explicitly trusts only your specific certificate without disabling validation entirely.

3Configure the ca option directly in your HTTPS requests

For programmatic control within your application, provide the CA certificate in your HTTPS request configuration:

javascript
const https = require('https');
const fs = require('fs');

const options = {
  hostname: 'your-server.com',
  port: 443,
  path: '/api',
  method: 'GET',
  ca: fs.readFileSync('./path/to/ca-cert.pem')
};

https.request(options, (res) => {
  console.log('Connected successfully');
}).end();

For popular libraries like Axios or node-fetch:

javascript
const axios = require('axios');
const https = require('https');
const fs = require('fs');

const agent = new https.Agent({
  ca: fs.readFileSync('./path/to/ca-cert.pem')
});

axios.get('https://your-server.com/api', { httpsAgent: agent });

This approach gives you fine-grained control per request.

4Obtain and install the complete certificate chain

If intermediate certificates are missing, obtain them from your Certificate Authority and create a complete chain file:

bash
# Concatenate certificates in order: leaf cert, intermediate(s), root CA
cat server.crt intermediate.crt root-ca.crt > full-chain.pem

# Verify the chain is valid
openssl verify -CAfile full-chain.pem server.crt

Then use this complete chain file with NODE_EXTRA_CA_CERTS or the ca option.

5For npm/package manager issues, configure npm to use the CA

If the error occurs during npm install with a private registry:

bash
# Set npm to use your custom CA certificate
npm config set cafile /path/to/ca-cert.pem

# Or configure for a specific registry
npm config set registry https://your-private-registry.com
npm config set cafile /path/to/ca-cert.pem

# For a single installation
npm install --cafile=/path/to/ca-cert.pem

For Yarn:

bash
yarn config set cafile /path/to/ca-cert.pem
6Update Node.js to the latest LTS version

Older Node.js versions may have outdated CA certificate bundles that do not recognize newer CAs:

bash
# Check current version
node --version

# Update using nvm (recommended for developers)
nvm install --lts
nvm use --lts

# Or download from nodejs.org and install

After updating, test if the error persists before implementing other fixes. Newer Node.js versions have more up-to-date root certificates.

Advanced notes

Why you should NEVER disable certificate validation in production:

While you may see recommendations to use NODE_TLS_REJECT_UNAUTHORIZED=0 or rejectUnauthorized: false, these completely disable certificate validation and expose your application to man-in-the-middle attacks. Never use these approaches in production code:

javascript
// โŒ NEVER DO THIS IN PRODUCTION
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

// โŒ ALSO NEVER DO THIS
const agent = new https.Agent({ rejectUnauthorized: false });

These shortcuts should only be used in controlled local testing environments and must be accompanied by comments explaining why.

Corporate proxy and firewall environments:

If you are behind a corporate proxy that intercepts HTTPS traffic, your company likely provides a custom CA certificate bundle. To resolve this:

1. Contact your IT/Security department to obtain the corporate root CA certificate(s) and any intermediate certificates
2. Request detailed instructions for installing them for Node.js specifically
3. Store certificates in a secure location accessible to your application
4. Use NODE_EXTRA_CA_CERTS or the programmatic ca option with the certificate bundle

Docker and containerized environments:

When running Node.js in containers, you need to add CA certificates to the container image:

dockerfile
# Copy CA certificate into container
COPY ca-cert.pem /usr/local/share/ca-certificates/company-ca.crt

# Update CA certificates (for Debian/Ubuntu-based images)
RUN update-ca-certificates

# Set environment variable for Node.js to use the certificate
ENV NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/company-ca.crt

Private registries and internal services:

For npm registries, Docker registries, or internal APIs with self-signed certificates:

- Store the CA certificate in version control (or in a secrets management system for production)
- Document the certificate location and chain order for your team
- Automate certificate updates when they rotate
- Monitor certificate expiry dates to prevent outages

Debugging certificate chains:

To troubleshoot which certificates are being presented:

bash
# View the complete certificate chain
openssl s_client -connect example.com:443 -showcerts

# Check certificate validity dates
openssl s_client -connect example.com:443 | openssl x509 -text -noout | grep -A2 "Validity"

# Verify a certificate chain
openssl verify -CAfile full-chain.pem server.crt

Frequently asked questions

What does "CERT_UNTRUSTED" mean?
js's built-in TLS/SSL verification has rejected a certificate during an HTTPS connection attempt. js maintains a list of trusted Certificate Authorities (CAs) and validates all certificates against this list by default. When you encounter this error, it means the certificate presented by the server is either self-signed (not issued by a recognized CA), expired, or part of a certificate chain that cannot be traced back to a trusted root CA.
How do I fix "CERT_UNTRUSTED"?
This error occurs when Node.js cannot verify the SSL/TLS certificate of a server you are trying to connect to. It typically happens with self-signed certificates, expired certificates, or missing intermediate certificates. The fix depends on whether you are in a development environment or production.
What causes "CERT_UNTRUSTED"?
Server is using a self-signed certificate not trusted by Node.js built-in CA list Missing intermediate certificates in the server certificate chain Corporate proxy or firewall intercepting HTTPS traffic with custom certificates
Is the "CERT_UNTRUSTED" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading