VSCode中Node服务报SELF_SIGNED_CERT_IN_CHAIN,主因是macOS系统钥匙串中企业自签名根证书过期或未设“始终信任”,需重装新证书至“系统”钥匙串并手动设为始终信任,再彻底重启VSCode验证。

VSCode 里 Node 服务(比如 npm start、webpack serve 或本地 API 调用)在 macOS 上突然报 SELF_SIGNED_CERT_IN_CHAIN,不是 Node 版本问题,也不是 VSCode 插件坏了,而是系统信任的自签名根证书过期了——尤其常见于企业环境或用了内部 CA 的开发机。
确认是不是系统级根证书过期
先别改代码或关 SSL 校验。打开终端,直接跑:
curl -v https://api.example.com 2>&1 | grep "issuer:"
如果输出里 issuer: 显示的是公司名(比如 O=MyCorp, CN=MyCorp Internal Root CA),且证书有效期已过(可用 openssl x509 -in /path/to/cert.pem -text -noout | grep After 查),那基本就是它了。macOS 不会自动更新这类手动导入的根证书,过期后 Node.js(包括 VSCode 内置终端调用的 Node)就会拒绝整条链。
- 检查证书是否还在钥匙串里:打开“钥匙串访问”,搜索关键词(如公司名),看对应根证书状态是否标为“已过期”或“不被信任”
- 注意:浏览器可能仍能访问(因 Chrome/Firefox 自带证书库),但 Node.js 只认系统钥匙串 +
NODE_EXTRA_CA_CERTS指向的文件 - VSCode 终端里运行
node -e "console.log(require('https').globalAgent.options.ca)",若返回undefined,说明 Node 没加载额外 CA,完全依赖系统信任链
重装或更新自签名根证书到系统钥匙串
拿到新的根证书(.cer 或 .pem 文件),双击安装进“系统”钥匙串(不是“登录”),然后手动设为“始终信任”:
- 右键证书 → “显示简介” → 展开“信任” → “当使用此证书时”下拉选“始终信任”
- 关闭窗口后,系统会提示输入密码保存更改——这步必须做,否则不生效
- 重启 VSCode(不是 reload window,是彻底退出再打开),让终端重新读取钥匙串状态
- 验证:在 VSCode 终端里执行
curl -I https://your-internal-api,应返回 200;再跑node -e "require('https').get('https://your-internal-api', r => r.on('data', console.log))",不再报错
临时绕过(仅调试用,勿提交)
生产环境或 CI 流程里绝不能关证书校验,但本地快速验证逻辑时,可临时加环境变量:
- 在 VSCode 终端里执行:
export NODE_TLS_REJECT_UNAUTHORIZED=0(只对当前终端生效) - 更安全一点的做法是只对特定请求绕过:在代码里加
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0',但必须确保只存在于if (process.env.NODE_ENV === 'development')分支内 - 绝对不要在
settings.json里写"http.proxyStrictSSL": false来解决这个错误——那是代理配置,和系统根证书无关,还可能让 Copilot 等服务连不上
VSCode 启动时没继承钥匙串信任?
有些 macOS 用户发现:终端里 curl 正常,但 VSCode 集成终端里照样报错。这是因为 VSCode 启动方式影响了钥匙串访问权限:
- 双击 Dock 图标启动 VSCode → 它以 GUI 应用身份运行,钥匙串访问受限(尤其启用了“自动锁屏”)
- 从终端启动:
code --new-window→ 继承 shell 环境,能正常读系统钥匙串 - 终极解法:在 VSCode 设置里搜
terminal.integrated.shellArgs.osx,设为["-i"],让 zsh 以交互模式启动,强制加载完整信任上下文
真正麻烦的不是证书过期本身,而是 macOS 钥匙串对 GUI 进程的静默限制——它不会报错,只会让 Node 的 TLS 握手静默失败。每次重装证书后,务必验证 VSCode 终端而非仅 Terminal.app。


















