错误信息
fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate problem: unable to get local issuer certificate
也可能输出为
- fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate OpenSSL verify result: unable to get local issuer certificate (20)
消息中的 URL 是你的远程仓库地址。使用 libcurl 8.22(可能还有其他较新版本)时,原因写作“SSL certificate OpenSSL verify result: unable to get local issuer certificate (20)”。Debian 和 Ubuntu 构建的 git 使用 GnuTLS,打印的则是“server verification failed: certificate signer not trusted”。
含义
git 的 HTTPS 传输层使用 libcurl,而基于 OpenSSL 的 libcurl 找不到签发 Git 服务器所发送最后一张证书的 CA。要么服务器没有发送中间证书,要么证书链终止于不在 git 所用证书包中的根证书(公司 CA、代理 CA)。在 Windows 上,这是典型症状,说明 Git for Windows 对照自己附带的 CA 文件检查证书,而不是对照 Windows 证书存储。
原因
Git for Windows 检查的是自己的 CA 文件,而不是 Windows 证书存储
常见使用默认的 OpenSSL 后端时,Git for Windows 对照它自带的 ca-bundle.crt 进行验证。IT 部门部署到 Windows 证书存储中的公司根证书和代理根证书不在这个文件里,因此浏览器能正常访问,克隆却失败。
使用私有 CA 的自托管 Git 服务器
常见自行部署的 GitLab、Gitea、Bitbucket Data Center 或 Azure DevOps Server 常常使用内部 CA 签发的证书,而 CI 镜像和新机器不信任这个 CA。
服务器没有发送中间证书
偶见如果消息中引用的颁发者是公共中间 CA,说明 Git 服务器或其反向代理只配置了叶子证书。
http.sslCAInfo 或 GIT_SSL_CAINFO 覆盖设置替换了证书包
偶见本来为某个内部主机设置的 CA 文件,如果配置在全局,就会替换所有远程仓库的默认证书包,于是访问公共主机开始失败(或者在文件被移动后出现相反的情况)。
修复方法
- 1.
Windows:让 git 改用 Windows 证书存储
设置 http.sslBackend schannel 后,Git for Windows 通过 Windows 本身进行验证,接受 Windows 信任的所有根证书,包括通过组策略部署的根证书。对企业网络来说,这才是干净的修复方法。
bash # Git for Windows: verify with the Windows certificate store, where IT deploys company roots git config --global http.sslBackend schannel git config --global --get http.sslBackend - 2.
只为一个 Git 主机信任该 CA
按 URL 限定作用范围的 http.<url>.sslCAInfo 只为该主机添加私有 CA;GIT_SSL_CAINFO 只作用于单条命令或单个作业。
bash git config --global http."https://git.example.com/".sslCAInfo /etc/ssl/private-ca/corp-root-ca.pem # one command or CI job only GIT_SSL_CAINFO=/etc/ssl/private-ca/corp-root-ca.pem git clone https://git.example.com/team/app.git - 3.
把根证书安装到系统证书包
在 Linux 上,libcurl 默认读取的就是系统证书包,因此把根证书添加到这里,可以同时修复 git、curl 和包管理器。
bash # Alpine / Debian / Ubuntu cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt && update-ca-certificates # RHEL / Fedora cp corp-root-ca.pem /etc/pki/ca-trust/source/anchors/ && update-ca-trust - 4.
查找替换了证书包的覆盖设置
--show-origin 会显示哪个配置文件设置了 CA 路径。删除本应只作用于单个主机的全局覆盖设置。
bash git config --show-origin --get-all http.sslCAInfo git config --show-origin --get-regexp 'http\..*\.sslcainfo' env | grep -E 'GIT_SSL_CAINFO|CURL_CA_BUNDLE|SSL_CERT_FILE' - 5.
临时诊断:只对一条命令跳过验证
-c http.sslVerify=false 只能用来确认诊断结果,切勿写入全局配置:它会暴露凭证,并让传输路径上的任何人都能篡改你拉取的代码。
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)fatal: unable to access 'https://git.example.com/team/app.git/': server verific…git over HTTPS with libcurl-gnutls (Debian, Ubuntu)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)