错误信息
npm error code SELF_SIGNED_CERT_IN_CHAIN
也可能输出为
- npm ERR! code SELF_SIGNED_CERT_IN_CHAIN
- npm error request to https://registry.example.com/lodash failed, reason: self-signed certificate in certificate chain
npm 10 及更高版本打印“npm error code SELF_SIGNED_CERT_IN_CHAIN”;npm 9 及更早版本打印“npm ERR! code SELF_SIGNED_CERT_IN_CHAIN”。接下来的几行以 errno 的形式重复该代码,并给出 URL 和“reason: self-signed certificate in certificate chain”。
npm (Node.js) — registry request over HTTPS
含义
与注册表的连接中出示的证书链终止于一张 Node.js 不认识的自签名根证书。对于 registry.npmjs.org,这意味着流量正被拦截并重新签名,几乎总是公司代理或带 HTTPS 扫描功能的杀毒软件所为:浏览器信任它们的根证书,npm 却不信任。
原因
企业网络中执行 TLS 检查的代理
常见Zscaler、Netskope、Palo Alto、Fortinet 等产品位于你的机器和注册表之间,并在证书链中出示自己的根证书。
带 HTTPS 扫描功能的杀毒软件或端点防护软件
偶见有些端点防护产品在本机拦截 TLS,并且只把它们的根证书注入操作系统的证书存储。
发送自身根证书的私有注册表
偶见证书由公司 CA 签名的内部注册表,即使在证书链中提供了根证书,仍然需要 Node.js 信任该根证书。
修复方法
- 1.
用 cafile 把代理的根证书提供给 npm
将根证书(从 IT 团队或操作系统的证书存储获取)导出为 PEM,并设置为 npm 的 cafile。此后 npm 只信任该文件中的 CA,因此如果笔记本电脑也会在公司网络之外使用,就要把公共根证书加入同一个文件,或者改用 NODE_EXTRA_CA_CERTS。
bash npm config set cafile /etc/ssl/private-ca/corp-proxy-root.pem npm install - 2.
或者设置 NODE_EXTRA_CA_CERTS
为 npm 和其他所有 Node.js 工具添加该根证书,而不替换 Node.js 的公共根证书。在 Windows 上,把它设置为用户环境变量,然后打开一个新终端。
bash # Windows (PowerShell): setx NODE_EXTRA_CA_CERTS C:\certs\corp-proxy-root.pem export NODE_EXTRA_CA_CERTS=/etc/ssl/private-ca/corp-proxy-root.pem npm install - 3.
或者让 Node.js 使用操作系统的证书存储
NODE_USE_SYSTEM_CA=1 让 Node.js(以及 npm)信任操作系统所信任的证书,在受管理的机器上,其中就包括代理的根证书。
bash # Managed machines already trust the proxy root in the OS store NODE_USE_SYSTEM_CA=1 npm install - 4.
临时诊断:--strict-ssl=false
仅用于确认问题出在信任上。包会运行安装脚本,所以接受未经验证的下载内容,正是供应链攻击进入开发者机器的途径;切勿把 strict-ssl=false 写进 .npmrc。
bash # Temporary diagnostic for one command only npm install --strict-ssl=false
相关错误
self-signed certificate in certificate chainNode.js tls / https / fetchnpm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLYnpm (Node.js)error Error: self-signed certificate in certificate chainYarn Classic (1.x)Error: ERR_PNPM_RESOLVING_NPM_RESOLVER_NETWORK_ERRORpnpm 12 (native binary, rustls)fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificat…git over HTTPS with libcurl + OpenSSL (Git for Windows default, macOS Homebrew, Alpine, RHEL)