Error message
fatal: unable to access 'https://git.example.com/team/app.git/': SSL certificate problem: self-signed certificate in certificate chain
Also printed as
- 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
The URL is your remote. OpenSSL 1.1.1-based builds print "self signed" without the hyphen; libcurl 8.22 prints "SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)".
What it means
The Git server (or something in front of it) sent a complete chain that ends in a self-signed root, and that root is not in the CA bundle git's libcurl uses. When this happens for public hosts such as github.com, the root almost always belongs to a TLS-inspecting proxy on your network; for self-hosted servers, to the company CA.
Why it happens
A corporate TLS-inspection proxy
commonZscaler, Netskope, Palo Alto, Fortinet and similar products decrypt and re-encrypt traffic with their own root. Windows trusts it through group policy; Git for Windows' bundled CA file, WSL, Docker and CI images do not.
The self-hosted Git server sends its private root
commonAn internal GitLab or Gitea that serves leaf, intermediate and the company root still needs the root installed on every client.
Antivirus HTTPS scanning
occasionalEndpoint security products with "HTTPS scanning" or "web shield" features insert their own root on the machine; it appears in this chain the same way a proxy's does.
How to fix it
- 1.
Identify the root
Print the chain for a public host. If the top certificate is named after your company or a security vendor, the connection is inspected and that root is what git needs to trust. If you do not recognise it at all, do not trust it: investigate first.
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: use the Windows certificate store
Git for Windows with http.sslBackend schannel trusts whatever Windows trusts, which on managed machines already includes the proxy root.
bash # Git for Windows: use the Windows certificate store, which already trusts the proxy root git config --global http.sslBackend schannel - 3.
Add the root to the bundle git uses
http.sslCAInfo replaces the default bundle, so build a file that contains the public roots plus the proxy or company root.
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.
Install the root system-wide on Linux
update-ca-certificates adds the root for git, curl, wget, pip and most other tools at once.
bash sudo cp corp-proxy-root.pem /usr/local/share/ca-certificates/corp-proxy-root.crt sudo update-ca-certificates - 5.
Temporary diagnostic: skip verification for one command
Only to confirm the diagnosis. Disabling verification for real work hands your Git credentials and source code to whoever terminates the connection.
bash # Diagnostic only, for one command git -c http.sslVerify=false ls-remote https://git.example.com/team/app.git
Related errors
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)