• git on Windows
  • Exact text checked with the real tool

schannel: SEC_E_UNTRUSTED_ROOT (0x80090325)

Also seen in: curl.exe on Windows, Git for Windows, Visual Studio, other programs that use Schannel

In one sentence

Windows could not link the Git server's certificate to a root in its trust store: usually a company or proxy root that is not installed, or a self-signed server.

Where you see it

In Git for Windows when it uses the Windows TLS library, Schannel (the installer option “Use the native Windows Secure Channel library”, or http.sslBackend=schannel):

$ git clone https://git.example.com/team/app.git
Cloning into 'app'...
fatal: unable to access 'https://git.example.com/team/app.git/': schannel: SEC_E_UNTRUSTED_ROOT (0x80090325) - The certificate chain was issued by an authority that is not trusted.

The curl.exe that ships with Windows prints the same text as curl: (60) schannel: SEC_E_UNTRUSTED_ROOT (0x80090325) - …. Versions of curl before 7.73.0, and the git versions built on them, printed schannel: next InitializeSecurityContext failed: SEC_E_UNTRUSTED_ROOT (0x80090325) - … (curl’s schannel.c). Microsoft lists SEC_E_UNTRUSTED_ROOT (0x80090325) as “The certificate chain was issued by an authority that is not trusted” (Windows error codes).

Check which TLS library your git uses:

git config --show-origin --get-all http.sslBackend

What it means

With Schannel, git lets Windows check the server’s certificate. Windows builds the certificate chain up to a root certificate in its Trusted Root Certification Authorities store. Here the chain ends at a root that this machine does not trust, or Windows could not reach any root. A browser on the same machine may still open the site, because Chrome, Edge and Firefox bring their own lists of trusted public roots in addition to the roots added to Windows.

Likely causes

The company’s root CA is not in the Windows store

Self-hosted Git servers often use a certificate from a company CA. Confirm which root the server’s chain ends at:

openssl s_client -connect git.example.com:443 -servername git.example.com -showcerts </dev/null 2>/dev/null | grep -E '^ [0-9]+ s:|^   i:'

Then look for that root under Trusted Root Certification Authorities in certmgr.msc (your account) or certlm.msc (the computer).

Fix: ask IT to deploy the root through Group Policy or Intune, or import it yourself:

# For your own account (no administrator rights; Windows asks you to confirm)
Import-Certificate -FilePath .\corp-root.cer -CertStoreLocation Cert:\CurrentUser\Root
# For the whole computer (administrator)
Import-Certificate -FilePath .\corp-root.cer -CertStoreLocation Cert:\LocalMachine\Root

Check the root’s fingerprint with IT before you import it. See How to trust a private root CA on Windows.

A TLS-inspection proxy re-signs your traffic

If public sites such as github.com fail too, a TLS-inspection proxy or an antivirus product is probably re-signing traffic with its own root. The -showcerts output above then shows the proxy’s name as the issuer. Fix: the proxy’s root must be in the Windows store, as above. See How to work behind a TLS-inspecting corporate proxy, safely.

The server uses a self-signed certificate

If the server’s certificate is its own issuer (the s: and i: lines are the same), there is no CA to trust. Fix: give the server a certificate from your company CA. As a stopgap for one server, you can trust exactly that CA certificate, and only for that host, with git’s OpenSSL backend:

git config --global http.sslBackend openssl
git config --global http.https://git.example.com/.sslCAInfo C:/certs/git-example-ca.pem

Note that with openssl, git no longer uses the Windows store: it uses its own CA bundle, and for this one host only the file you configure. With Schannel, http.schannelUseSSLCAInfo makes git use http.sslCAInfo instead of the Windows store (git-config).

Windows cannot reach the missing pieces

Windows downloads missing intermediates and trusted public roots when it needs them. On build agents and servers without internet access, that fails, and even a public root can be missing. Fix: make the server send its full chain (How to build the full chain file your server needs), and let IT distribute roots to disconnected machines (Microsoft guidance). certutil -verifyctl AuthRoot | findstr /i "lastsynctime" shows when Windows last updated its root list.

Check yours

Try it: Chain checkerOpen the full tool

Runs in your browser. Nothing you paste is sent anywhere.

Every certificate the server sends, leaf first. The output of openssl s_client -showcerts -connect example.com:443 works as it is: we ignore the text around the certificates.

Paste the certificates from openssl s_client -showcerts. The checker shows which root the chain needs, and flags root names of known HTTPS-inspection products.

Learn why

In the gameLevel 12: Who do we trust?Registry of Roots, Keystone. In development

Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.

Last reviewed Edition 0.9