错误信息
npm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLY
也可能输出为
- npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- npm error request to https://registry.example.com/lodash failed, reason: unable to get local issuer certificate
npm 10 及更高版本以“npm error”作为行前缀;npm 9 及更早版本使用的是“npm ERR!”。接下来的几行以 errno 的形式重复该代码,并给出 URL 和“reason: unable to get local issuer certificate”。
npm (Node.js) — registry request over HTTPS
含义
npm 无法验证注册表的 TLS 证书:它收到的证书链指向的根证书不在 Node.js 信任的 CA 之列。npm 运行在 Node.js 上,而 Node.js 默认只信任其内置的 Mozilla 根证书列表,因此安装在操作系统中的公司根证书或代理根证书不会被使用。请求在下载任何包之前就失败了。
原因
执行 TLS 检查的代理对 registry.npmjs.org 重新签名
常见在公司网络中,代理出示由它自己的 CA 签发的证书。浏览器通过操作系统信任这个 CA,而 npm 经由 Node.js 判断,不信任它。
使用公司证书的私有注册表
常见Artifactory、Nexus、Verdaccio 或 GitHub Enterprise 的包注册表常常使用内部 CA 签发的证书,而该 CA 不在 Node.js 的根证书列表中。
根证书在操作系统的证书存储中,但 Node.js 使用自己的列表
偶见update-ca-certificates、macOS 钥匙串和 Windows 证书存储都不会影响 Node.js,除非明确让它使用系统证书存储。
修复方法
- 1.
设置 npm 的 cafile
npm config set cafile 让 npm 指向一个 PEM 文件,其中包含注册表请求应信任的 CA 证书(保存在你的用户级 .npmrc 中;如需写入其他级别,使用 --location=project 或 --location=global)。此后 npm 只信任该文件中的 CA,因此如果 npm 还要访问不在你的 CA 覆盖范围内的注册表,就要把公共根证书也加进去。
bash # npm's own setting: a PEM file with the CA(s) to trust for registry requests npm config set cafile /etc/ssl/private-ca/corp-root-ca.pem npm config get cafile - 2.
使用 NODE_EXTRA_CA_CERTS
对于每个带着该变量启动的 Node.js 进程(包括 npm、npx 和构建工具),该文件中的证书都会添加到 Node.js 的内置根证书中。
bash # Adds to Node.js's built-in roots for npm and every other Node.js tool in this shell export NODE_EXTRA_CA_CERTS=/etc/ssl/private-ca/corp-root-ca.pem npm install - 3.
使用操作系统的证书存储
设置 NODE_USE_SYSTEM_CA=1 后(适用于支持 --use-system-ca 的 Node.js 版本),npm 会信任 IT 部门部署在操作系统中的根证书。
bash # Trust what the OS trusts (corporate roots deployed by IT) NODE_USE_SYSTEM_CA=1 npm install - 4.
CI:通过环境提供 CA
把公司根证书(它是公开的)提交到仓库,或者在作业中获取它,并为运行 npm 的步骤设置 NODE_EXTRA_CA_CERTS。
yaml # CI job (GitHub Actions syntax): provide the CA to npm without touching the image env: NODE_EXTRA_CA_CERTS: ${{ github.workspace }}/certs/corp-root-ca.pem steps: - run: npm ci - 5.
临时诊断:只对一条命令使用 --strict-ssl=false
为注册表请求禁用证书验证。它能确认诊断,但会让传输路径上的任何人替换包,而这些包随后会在你的机器上运行安装脚本;切勿把它保留在 .npmrc 中。
bash # Temporary diagnostic for one command only, never in .npmrc npm install --strict-ssl=false
相关错误
unable to get local issuer certificateNode.js tls / https / fetchnpm error code SELF_SIGNED_CERT_IN_CHAINnpm (Node.js)error Error: unable to get local issuer certificateYarn Classic (1.x); Yarn 4 prints the aliasError: ERR_PNPM_RESOLVING_NPM_RESOLVER_NETWORK_ERRORpnpm 12 (native binary, rustls)There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FA…pip