# Git "SSL certificate problem": fix clone and push errors

> Git's "SSL certificate problem: unable to get local issuer certificate" means libcurl could not verify the server. Fix the chain or set http.sslCAInfo.

Source: https://ssl.sh/errors/git-ssl-certificate-problem/
Last updated: 2026-11-10

**This Git error means the HTTPS connection to your remote failed certificate verification: Git could not chain the server's certificate to a CA in its bundle.** It almost always involves a self-hosted Git server with an incomplete chain or a private CA, or a corporate proxy that intercepts HTTPS.

## Quick fix

Fix the server if its chain is incomplete; otherwise trust the company root for that host only.

First check what the Git server sends:

```bash
openssl s_client -connect git.example.com:443 -servername git.example.com -showcerts </dev/null
```

- **Only one certificate, verify code 20 or 21:** the server is missing its intermediate. Fix it on the server (see below); every client benefits.
- **Full chain, issuer is your company CA or proxy:** trust that root for this host only:

```bash
git config --global http."https://git.example.com/".sslCAInfo /path/to/company-root.pem
```

- **On Windows** with the root already in the Windows store (typical for domain-joined PCs):

```bash
git config --global http.sslBackend schannel
```

## Causes

### 1. The Git server sends an incomplete chain

Self-hosted GitLab, Gitea and Bitbucket instances are often configured with only the leaf certificate. See [missing intermediate certificate](https://ssl.sh/errors/missing-intermediate-certificate/).

- **Confirm:** `openssl s_client -showcerts` lists one certificate.
- **Fix:** GitLab Omnibus reads `/etc/gitlab/ssl/<hostname>.crt`; put the leaf followed by the intermediates in that file and run `gitlab-ctl hup nginx`. For Gitea or a reverse proxy, configure the full chain in Nginx or Apache. See [missing intermediate certificate](https://ssl.sh/errors/missing-intermediate-certificate/).

### 2. Private or self-signed CA

Internal servers often use an internal CA. The message may also read `self-signed certificate in certificate chain`.

- **Confirm:** the top issuer in the chain is an internal name.
- **Fix:** set `http.sslCAInfo` as above, or add the root to the OS trust store so Git, curl and other tools all pick it up. See [self-signed certificate in certificate chain](https://ssl.sh/errors/self-signed-certificate-in-certificate-chain/).

### 3. Corporate TLS-inspecting proxy

- **Confirm:** connections to public hosts such as github.com also fail, and the issuer names a security vendor.
- **Fix:** get the proxy root from IT. On Windows, `http.sslBackend schannel` usually solves it at once because IT has already pushed that root into the Windows store.

### 4. Outdated CA bundle on the client

Old Linux distributions and minimal containers can lack newer roots.

- **Confirm:** `GIT_CURL_VERBOSE=1 git ls-remote https://git.example.com/team/repo.git` shows the CA file in use; it is missing or old.
- **Fix:** update the `ca-certificates` package.

## Fixes by environment

Git uses libcurl, so the fix matches [curl error 60](https://ssl.sh/errors/curl-60-ssl-certificate-problem/): trust the right root, system-wide or with `http.sslCAInfo`.

**Linux (Debian/Ubuntu)**

```bash
sudo cp company-root.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
```

On RHEL-family systems copy to `/etc/pki/ca-trust/source/anchors/` and run `update-ca-trust`.

**Windows (Git for Windows):** choose between the bundled OpenSSL backend with its own CA file, or Schannel with the Windows store. `git config --global http.sslBackend schannel` switches to the store. To keep OpenSSL, set `http.sslCAInfo` to a bundle that includes your root.

**macOS:** add the root to the System keychain for tools that use it, and set `http.sslCAInfo` if your Git build uses its own OpenSSL bundle (common with Homebrew).

**CI runners and containers:** install `ca-certificates`, copy the internal root into the image, and run `update-ca-certificates`. You can also set `GIT_SSL_CAINFO=/path/to/root.pem` for a single job.

**Per repository:** `git config http.sslCAInfo /path/to/root.pem` inside the repository applies only there.

## Don't do this

- **`git config --global http.sslVerify false`.** Disables verification for every HTTPS remote, including github.com, for that user.
- **`GIT_SSL_NO_VERIFY=true` in CI.** Pipelines often carry deploy tokens; an attacker in the path gets them and can inject code into builds.
- **`git -c http.sslVerify=false clone` as a one-off.** The repository you cloned keeps working, so nobody fixes the root cause, and the command ends up copied into documentation.
