错误信息
npm error code CERT_HAS_EXPIRED
也可能输出为
- npm ERR! code CERT_HAS_EXPIRED
- npm error request to https://registry.example.com/lodash failed, reason: certificate has expired
npm 10 及更高版本打印“npm error code CERT_HAS_EXPIRED”;npm 9 及更早版本打印“npm ERR! code CERT_HAS_EXPIRED”。接下来的几行给出 URL,并附有“reason: certificate has expired”。
npm (Node.js) — registry request over HTTPS
含义
按这台机器的时钟,npm 从注册表(或中间的代理)收到的证书链中,有一张证书已超过过期日期。对公共注册表来说,这几乎从不意味着 npm 自己的证书过期了:它指向的是固定在你 npm 配置中的旧 CA、过时的 Node.js 根证书列表、代理证书,或者不准确的时钟。对私有注册表来说,服务器的证书可能确实已经过期。
原因
私有注册表的证书已过期
常见自托管的 Nexus、Artifactory 或 Verdaccio 实例以及企业代理,其证书靠手动续期。
版本很旧、根证书过时的 Node.js
偶见Node.js 把根证书列表内置在二进制文件中;在某个 CA 更换根证书之前发布的版本,可能只认识已过期的旧根证书,因此当前版本能验证通过的连接,在这些版本上会失败。
用 ca 或 cafile 设置固定的旧 CA
偶见多年前留在 .npmrc 中的 ca= 或 cafile= 条目会替换 Node.js 在注册表请求中使用的默认根证书,因此 npm 一直在用那张已经过期的旧证书做验证。
系统时钟不准确
偶见修改配置之前,先检查虚拟机、容器以及没有电池供电时钟的设备上的日期。
修复方法
- 1.
确认涉及的是哪个注册表和哪张证书
查看配置的注册表,以及它所提供证书的到期日期。私有注册表上过期的证书必须在服务器上续期。
bash npm config get registry echo | openssl s_client -connect registry.example.com:443 -servername registry.example.com 2>/dev/null \ | openssl x509 -noout -subject -enddate - 2.
删除过时的 ca 或 cafile 设置
npm config list 会显示每一级 .npmrc 中的设置;删除指向旧证书的 ca 或 cafile 条目(或者更新它们引用的文件)。
bash # An old CA pinned in .npmrc replaces the default roots: list and remove it npm config list | grep -E '^;? *(ca|cafile)' npm config delete ca npm config delete cafile - 3.
升级 Node.js 和 npm
仍在维护的 Node.js 版本带有最新的根证书列表;之后再升级 npm。
bash node -v && npm -v # Node.js bundles its root list; very old releases carry expired roots # upgrade Node.js to a maintained release (nvm, fnm, volta or your OS packages), then: npm install -g npm@latest