命令行工具
npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY 的修法
npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLYUNABLE_TO_GET_ISSUER_CERT_LOCALLY 的意思是:npm 镜像源出示的 HTTPS 证书,最终链到了一张 Node.js 不信任的根证书。 大多数机器上,这是公司代理在重新签名流量,或者私有仓库用了内部 CA。
快速修复
把证书链顶端的根证书交给 Node.js 就能解决,通常用 NODE_EXTRA_CA_CERTS。先看 npm 实际看到的证书是谁签发的:
npm config get registry
openssl s_client -connect registry.npmjs.org:443 -servername registry.npmjs.org </dev/null 2>/dev/null | openssl x509 -noout -issuer
如果用的是国内镜像,把上面的主机名换成 registry.npmmirror.com。签发者如果是公司名或安全厂商,向 IT 要这张根证书(PEM 格式),对所有 Node.js 进程生效:
export NODE_EXTRA_CA_CERTS=/path/to/company-root.pem
npm install
写进 shell 配置、CI 变量或 Dockerfile 里长期生效。也可以只配置 npm:
npm config set cafile /path/to/ca-bundle.pem # 文件里要包含 npm 需要的全部根证书
新版 npm 的输出是 npm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLY,修法一样。
原因
最常见的是公司代理解密 HTTPS,其次是私有仓库用了内部 CA。
1. 公司代理、上网行为管理或杀毒软件解密 HTTPS
- 确认: 上面打印的签发者不是公网 CA;只在公司网络或连 VPN 时报错。
- 修复: 用
NODE_EXTRA_CA_CERTS加入代理根证书。如果还需要配置代理地址,用npm config set proxy和https-proxy设置成 IT 提供的地址。
2. 私有仓库用了内部 CA
公司自建的 Nexus、Artifactory、Verdaccio、GitLab 包仓库经常用内部 CA 签发的证书。
- 确认:
npm config get registry是内网地址,签发者是公司内部 CA。 - 修复: 用
NODE_EXTRA_CA_CERTS信任内部根证书,或者在项目.npmrc里配置cafile。如果私有仓库证书链不完整,报错会变成 unable to verify the first certificate,需要修仓库前面的反向代理。
3. ca 或 cafile 配置把默认列表替换掉了
- 确认:
npm config list里有ca或cafile,可能来自项目、用户或全局的.npmrc。 - 修复: 让这个文件包含所有需要的根证书(公网的和私有的),或者删掉它改用
NODE_EXTRA_CA_CERTS。
4. Node.js 或 npm 版本太老
很老的版本内置的 CA 列表也很旧。
- 修复: 升级到仍在维护的 Node.js LTS 版本。国内下载 Node.js 安装包可以用 npmmirror 提供的二进制镜像,或者用 nvm、fnm 等版本管理工具配置国内镜像地址。
5. 镜像地址过时或已停用
项目或用户目录里的 .npmrc 常常还指向已经换了域名或停用的镜像。镜像换了域名、内部镜像换成了内部 CA 签发的证书,都会导致这个报错,或者变成 CERT_HAS_EXPIRED 之类的错误。典型例子是还在用旧淘宝镜像域名的老项目。
- 确认:
npm config get registry和npm config list显示的地址不是你预期的;对它执行npm ping失败。 - 修复: 用
npm config set registry https://registry.npmmirror.com改成当前地址,或者删掉.npmrc里那一行过时的配置。团队项目要把修改提交到仓库,其他同事才不会继续报错。
各环境修法
Windows、macOS、Docker 和 CI 上都用 NODE_EXTRA_CA_CERTS 指向 PEM 根证书,并且要在 npm 启动之前设置好。
Windows: 先从 Windows 证书库把根证书导出为“Base64 编码 X.509”格式,再执行 setx NODE_EXTRA_CA_CERTS C:\certs\company-root.pem,然后重新打开终端。
macOS / Linux: 在 ~/.zshrc 或 ~/.bashrc 中加入 export NODE_EXTRA_CA_CERTS=...。
Docker:
COPY company-root.pem /usr/local/share/ca-certificates/company-root.crt
ENV NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/company-root.crt
RUN npm config set registry https://registry.npmmirror.com && npm ci
CI(GitLab CI、Jenkins、云效、GitHub Actions): 把 PEM 存成文件类型的密钥,npm ci 之前导出 NODE_EXTRA_CA_CERTS。
安装时会下载二进制文件的包(如浏览器内核、原生模块)用的是它们自己的 HTTPS 请求,只有 NODE_EXTRA_CA_CERTS 能覆盖,npm 的 cafile 管不到。
不要这样做
关闭 strict-ssl、关闭 TLS 校验或改用 http://,都会让包在下载途中可以被篡改。
npm config set strict-ssl false。 npm 会接受镜像源的任何证书,中间人可以返回被篡改的包,再通过安装脚本在你机器上执行代码。NODE_TLS_REJECT_UNAUTHORIZED=0 npm install。 风险一样,而且作用于安装过程中的所有连接。- 把镜像源改成
http://。 传输过程失去加密和完整性保护。
常见问题
cafile 和 NODE_EXTRA_CA_CERTS 用哪个?
公司代理环境下一般选 NODE_EXTRA_CA_CERTS。cafile 只由 npm 读取,和 ca 一样会替换 npm 默认的 CA 列表,文件里必须包含所有需要的根证书。NODE_EXTRA_CA_CERTS 是在 Node.js 默认列表基础上追加,对所有 Node.js 进程有效,安装时下载二进制文件的 postinstall 脚本也能用上。
为什么只在公司网络里报错?
公司的代理或上网行为管理在解密 HTTPS,并用自己的根证书重新签名。在家直连镜像源时看到的是公网证书。向 IT 要这张代理根证书即可。
用 npmmirror 国内镜像也会报这个错吗?
镜像本身证书正常时不会。但如果 .npmrc 里还写着已停用的旧淘宝镜像域名 registry.npm.taobao.org,就会出现证书报错(通常是证书过期),请改为 https://registry.npmmirror.com。见 CERT_HAS_EXPIRED。
yarn、pnpm 要单独配置吗?
它们都运行在 Node.js 上,设置 NODE_EXTRA_CA_CERTS 后都能生效。它们也各有自己的 CA 配置项(如 yarn 的 cafile、Yarn Berry 的 caFilePath),想按工具单独配置时才需要。