'self signed certificate in certificate chain' — fix Node TLS
Quick answer: self signed certificate in certificate chain means Node doesn't trust the TLS chain it was given — usually a corporate proxy intercepting traffic, a private CA, or a missing intermediate cert. The safe fix is to trust the CA via NODE_EXTRA_CA_CERTS=/path/to/ca.pem, not to disable verification. Never set NODE_TLS_REJECT_UNAUTHORIZED=0 in production — it turns the security off entirely.
What the error looks like
Node rejects the connection because it can't build a trusted chain:
Error: self signed certificate in certificate chain
code: 'SELF_SIGNED_CERT_IN_CHAIN'
# a close cousin:
Error: unable to verify the first certificate
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
Node verifies TLS against a built-in set of public CAs. A private or intercepting CA isn't in that set, so a chain that's perfectly valid on your network looks untrusted to Node.
Why it happens
A corporate MITM proxy
A security appliance re-signs HTTPS with its own CA that Node doesn't know.
A private/internal CA
Internal services use a company CA that isn't in the public trust store.
Incomplete chain
The server omits an intermediate, so Node can't link the leaf to a trusted root.
npm/registry behind a proxy
Installs fail with the same error when the proxy injects its CA.
Fix it safely in three steps
Identify the CA in the way
openssl s_client -connect example.com:443 -showcerts
# Look for a corporate/internal issuer at the top of the chain.Trust that CA explicitly
# point Node at the extra CA bundle (do NOT disable verification)
export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/corp-ca.pem
# npm equivalent:
npm config set cafile /etc/ssl/certs/corp-ca.pemIf it's your server, send the full chain
# serve leaf + intermediates (fullchain.pem), not just the leaf
ssl_certificate /etc/letsencrypt/live/app/fullchain.pem;Add the CA — never turn verification off
The correct fix is to make Node trust the specific CA, via NODE_EXTRA_CA_CERTS or the system trust store. Setting NODE_TLS_REJECT_UNAUTHORIZED=0 disables certificate checking globally — it silences the error by removing the protection, opening you to interception. Trust the CA; don't blind the client.
Verified channels, not blind trust
Disabling certificate verification is the opposite of how Infraveil works. On your own servers, the agent verifies signatures on what it runs and signs its traffic to the control plane — trust comes from a checkable signature, not from turning checks off. The same instinct fixes this error: add the CA, keep verification on.
Frequently asked questions
What does 'self signed certificate in certificate chain' mean?
Node couldn't build a trust path from the server's certificate to a CA it trusts — usually because a corporate proxy or private CA signed the chain, or an intermediate is missing.
How do I fix it safely?
Trust the specific CA: export NODE_EXTRA_CA_CERTS=/path/to/ca.pem (or add it to the system trust store). For your own server, serve the full chain including intermediates.
Is NODE_TLS_REJECT_UNAUTHORIZED=0 a good fix?
No. It disables TLS certificate verification entirely and exposes you to man-in-the-middle attacks. Use it only for throwaway local debugging, never in production.
Why does this happen behind a corporate network?
A security proxy intercepts HTTPS and re-signs it with the company's own CA, which isn't in Node's built-in trust store. Add that CA via NODE_EXTRA_CA_CERTS.