错误信息
fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate problem: self-signed certificate in certificate chain
也可能输出为
- fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)
- SSL certificate problem: self signed certificate in certificate chain
消息中的 URL 是你的远程仓库地址。基于 OpenSSL 1.1.1 的构建版本打印不带连字符的“self signed”;libcurl 8.22 打印的是“SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)”。
含义
Git 服务器(或位于它前面的某个组件)发送了一条完整的证书链,这条链终止于一张自签名根证书,而该根证书不在 git 所用 libcurl 的 CA 证书包中。如果访问 github.com 这样的公共主机时出现这种情况,这张根证书几乎总是属于你所在网络中执行 TLS 检查的代理;如果是自托管服务器,则属于公司 CA。
原因
企业网络中执行 TLS 检查的代理
常见Zscaler、Netskope、Palo Alto、Fortinet 等产品会解密流量,再用自己的根证书重新加密。Windows 通过组策略信任这个根证书;Git for Windows 自带的 CA 文件、WSL、Docker 以及 CI 镜像则不信任它。
自托管 Git 服务器发送了自己的私有根证书
常见即使内部的 GitLab 或 Gitea 提供了叶子证书、中间证书和公司根证书,每个客户端上仍然需要安装该根证书。
杀毒软件的 HTTPS 扫描
偶见带有“HTTPS 扫描”或“网页防护”功能的端点安全产品会在本机插入自己的根证书;它出现在这条证书链中的方式与代理的根证书相同。
修复方法
- 1.
弄清这是谁的根证书
打印某个公共主机的证书链。如果最上层的证书以你所在公司或某家安全厂商命名,说明连接正在被检查,git 需要信任的正是这张根证书。如果完全认不出它,就不要信任:先调查清楚。
bash openssl s_client -connect github.com:443 -servername github.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' # A root named after your company or a security vendor = interception proxy - 2.
Windows:使用 Windows 证书存储
设置了 http.sslBackend schannel 的 Git for Windows 会信任 Windows 信任的一切,而在受管机器上,这已经包括代理的根证书。
bash # Git for Windows: use the Windows certificate store, which already trusts the proxy root git config --global http.sslBackend schannel - 3.
将根证书添加到 git 使用的证书包中
http.sslCAInfo 会替换默认证书包,因此要构建一个文件,同时包含公共根证书以及代理或公司的根证书。
bash # Linux/macOS/WSL: append the proxy root to a bundle that keeps the public roots cat /etc/ssl/certs/ca-certificates.crt corp-proxy-root.pem > ~/.config/git/ca-bundle.pem git config --global http.sslCAInfo ~/.config/git/ca-bundle.pem - 4.
在 Linux 上把根证书安装到整个系统
update-ca-certificates 会一次性为 git、curl、wget、pip 和大多数其他工具添加该根证书。
bash sudo cp corp-proxy-root.pem /usr/local/share/ca-certificates/corp-proxy-root.crt sudo update-ca-certificates - 5.
临时诊断:只对一条命令跳过验证
仅用于确认诊断结果。在实际工作中禁用验证,等于把你的 Git 凭证和源代码交给终止该连接的任何一方。
bash # Diagnostic only, for one command git -c http.sslVerify=false ls-remote https://git.example.com/team/app.git
相关错误
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)curl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)npm error code SELF_SIGNED_CERT_IN_CHAINnpm (Node.js)[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certifi…Python ssl module (OpenSSL)