<!-- https://pkizerotohero.com/guides/add-root-ca-windows/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Add a private root CA to the Windows Trusted Root store with PowerShell, certutil, Group Policy or Intune, prove it worked, and fix apps that ignore it.

Source: https://pkizerotohero.com/guides/add-root-ca-windows/ · Last reviewed: 2026-10-20

How-to guide · Trust a CA

# How to trust a private root CA on Windows

**In one sentence:**

Your Windows computer, or a whole fleet, trusts your organisation's private root CA, and you know which apps still need their own setting.

Task

[Trust a CA](https://pkizerotohero.com/guides/#task-trust)

Platforms

- Windows

Who it is for

- [IT ops](https://pkizerotohero.com/start/#itops)
- [Developer](https://pkizerotohero.com/start/#developer)

Level

Practitioner · 5 steps

## Before you start

- The [root certificate](https://pkizerotohero.com/handbook/glossary/#root-certificate) of your [private CA](https://pkizerotohero.com/handbook/glossary/#private-ca) as a file (`.cer` or `.crt`, DER or PEM). Only the public certificate: never a `.pfx` and never a private key.
- Its SHA-256 [fingerprint](https://pkizerotohero.com/handbook/glossary/#fingerprint), from a channel you trust (your PKI team’s HTTPS intranet page, a signed ticket), not from the email that carried the file.
- Administrator rights for the computer-wide store. Your own user store needs none.
- For many machines: rights to edit a Group Policy Object or an Intune configuration profile.

Why it matters: a root in the Windows [trust store](https://pkizerotohero.com/handbook/glossary/#trust-store) can vouch for **any** name, for every program that uses Windows certificate checking. Add only roots your organisation controls.

## Steps

### 1. Check the file before you trust it

`certutil -dump` only reads the file. It accepts PEM and DER. This is the output for our throwaway test root on Windows 11, shortened:

```powershell
certutil -dump corp-root.crt
```

```text
X509 Certificate:
Version: 3
Serial Number: 15d0a60c3f02987ab1646cb51bba6b3d07450314
...
Issuer:
    CN=Example Corp Root CA
    O=Example Corp
    C=BE
...
 NotAfter: 2036-10-17 3:43 AM

Subject:
    CN=Example Corp Root CA
...
        Subject Type=CA
...
Root Certificate: Subject matches Issuer
Cert Hash(sha1): 3a5470d89c8577fedcb81710def42371214af708
Cert Hash(sha256): bc02a4f5dc68b3fdcdc478030e308cb59d6da0845aa0b4333660788e96c22e01
```

Three things to confirm:

- `Cert Hash(sha256)` equals the fingerprint your PKI team published. OpenSSL prints the same value with colons: `openssl x509 -in corp-root.crt -noout -fingerprint -sha256`.
- `Subject Type=CA` and `Root Certificate: Subject matches Issuer`. If the subject and issuer differ, you have an [intermediate](https://pkizerotohero.com/handbook/glossary/#intermediate-certificate) or a server certificate, not a root.
- `NotAfter` is years away.

You can also paste the PEM text into the decoder. It runs in your browser; never paste a private key into any website.

*Interactive tool: Certificate decoder (runs in the browser at [/tools/decoder/](https://pkizerotohero.com/tools/decoder/))*

### 2. Choose the store

| Store (console name) | PowerShell path | Who trusts it |
| --- | --- | --- |
| Trusted Root Certification Authorities, computer | `Cert:\LocalMachine\Root` | Every user and every service. The normal choice. Needs administrator rights. |
| Trusted Root Certification Authorities, current user | `Cert:\CurrentUser\Root` | Only you. Services running under other accounts do not see it. |
| Intermediate Certification Authorities | `Cert:\LocalMachine\CA` | For intermediates only. Never put an intermediate in a Root store. |

The Personal store (`My`) holds certificates that have private keys, such as a server’s own certificate. It is not a trust store.

### 3. Import it on one computer

In PowerShell **as administrator**, with the [Import-Certificate](https://learn.microsoft.com/en-us/powershell/module/pki/import-certificate) cmdlet:

```powershell
Import-Certificate -FilePath .\corp-root.cer -CertStoreLocation Cert:\LocalMachine\Root
```

Or with [certutil](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil#-addstore), in an administrator Command Prompt or PowerShell:

```powershell
certutil -addstore -f Root corp-root.cer
```

For your own account only, use `Cert:\CurrentUser\Root` or `certutil -user -addstore Root corp-root.cer`. Windows then shows a Security Warning with the certificate’s SHA-1 thumbprint: compare it with `Cert Hash(sha1)` from step 1 before you click Yes.

Without the command line: run `certlm.msc` (computer) or `certmgr.msc` (current user), open **Trusted Root Certification Authorities**, right-click **Certificates**, choose **All Tasks** > **Import** and follow the wizard.

If a tool rejects a PEM file, convert it to DER first ([how to convert between DER and PEM](https://pkizerotohero.com/guides/convert-der-pem/)):

```bash
openssl x509 -in corp-root.crt -outform DER -out corp-root.cer
```

### 4. Or roll it out to many computers

Hand-imports drift. On a fleet, pick one central method:

- **Group Policy** ([Microsoft’s procedure](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/distribute-certificates-to-client-computers-by-using-group-policy)): edit a GPO linked to the right OU, open **Computer Configuration\\Policies\\Windows Settings\\Security Settings\\Public Key Policies**, right-click **Trusted Root Certification Authorities** and choose **Import**. Computers pick it up at the next policy refresh; `gpupdate /force` speeds up one machine.
- **Intune** ([trusted certificate profiles](https://learn.microsoft.com/en-us/intune/device-configuration/certificates/trusted-root-profiles)): **Devices** > **Manage devices** > **Configuration** > **Create**, platform Windows 10 and later, **Templates** > **Trusted certificate**. Upload the DER `.cer` file and choose the destination store **Computer certificate store - Root**. Deploy intermediates in a separate profile to **Computer certificate store - Intermediate**.
- **Active Directory**: `certutil -dspublish -f corp-root.cer RootCA` publishes the root to the directory’s Trusted Root store, which domain members download. An enterprise AD CS root is published there when it is installed.

### 5. Point the apps that ignore the Windows store

Many tools use their own list of roots. Check each one your users run:

| Program | Uses the Windows store? | What to do |
| --- | --- | --- |
| Edge, Chrome | Yes: Chrome reads roots added to the computer and user stores ([Chrome Root Store FAQ](https://chromium.googlesource.com/chromium/src/+/main/net/data/ssl/chrome_root_store/faq.md)) | Restart the browser |
| Firefox | Yes, by default since Firefox 120, through `security.enterprise_roots.enabled` ([Mozilla](https://wiki.mozilla.org/CA/AddRootToFirefox)) | Restart Firefox |
| .NET, PowerShell, `curl.exe` from Windows | Yes | Nothing |
| Git for Windows | Only with the Schannel backend | `git config --global http.sslBackend schannel` |
| Node.js, npm | No | `node --use-system-ca` (Node.js 22.15 or later), or `NODE_EXTRA_CA_CERTS`: see [Python, Node.js and npm](https://pkizerotohero.com/guides/trust-ca-python-node/) |
| pip 24.2 and later | Yes, in addition to its own bundle | Nothing |
| Python `requests` | No, it uses certifi | See [Python, Node.js and npm](https://pkizerotohero.com/guides/trust-ca-python-node/) |
| Java | No, it uses `cacerts` | See [Java trust stores](https://pkizerotohero.com/guides/add-root-ca-java/) |
| WSL, Docker containers | No, they are Linux | See [Linux](https://pkizerotohero.com/guides/add-root-ca-linux/) |

## Check it worked

List the root in the computer store. This view also includes roots that arrive through Group Policy or Active Directory:

```powershell
Get-ChildItem Cert:\LocalMachine\Root | Where-Object Subject -like '*Example Corp Root CA*' | Format-List Subject, Thumbprint, NotAfter
```

Then ask Windows to verify the root file. Before the import, our test machine said:

```powershell
certutil -verify corp-root.crt
```

```text
ChainContext.dwErrorStatus = CERT_TRUST_IS_UNTRUSTED_ROOT (0x20)
...
A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.
0x800b0109 (-2146762487 CERT_E_UNTRUSTEDROOT)
Verifies against UNTRUSTED root
```

After the import, `CERT_E_UNTRUSTEDROOT` disappears. Finally, open an internal site in Edge, or test from the command line with the `curl.exe` that ships with Windows:

```powershell
curl.exe -sS -o NUL -w "%{http_code}`n" https://intranet.example.com/
```

A status code such as `200` means the TLS check passed.

## If something goes wrong

- **The browser still says [`NET::ERR_CERT_AUTHORITY_INVALID`](https://pkizerotohero.com/errors/chrome-err-cert-authority-invalid/) or [`SEC_ERROR_UNKNOWN_ISSUER`](https://pkizerotohero.com/errors/firefox-sec-error-unknown-issuer/).** The root is in the wrong store (Personal or Intermediate), the browser was not restarted, or the server’s chain ends at a different root. Compare the issuer in the browser’s certificate viewer with your file.
- **A service or script still fails** with [`Could not establish trust relationship`](https://pkizerotohero.com/errors/powershell-could-not-establish-trust/) or [`The remote certificate is invalid`](https://pkizerotohero.com/errors/dotnet-remote-certificate-invalid/). It probably runs under another account, which does not see your current-user store: import into the computer store.
- **Windows works, but Node.js, Java, Python or Git fail.** They use their own store: see step 5 and [`SELF_SIGNED_CERT_IN_CHAIN`](https://pkizerotohero.com/errors/node-self-signed-cert-in-chain/), [`PKIX path building failed`](https://pkizerotohero.com/errors/java-pkix-path-building-failed/) or [`schannel: SEC_E_UNTRUSTED_ROOT`](https://pkizerotohero.com/errors/git-schannel-sec-e-untrusted-root/).
- **Windows works, but other clients fail with “unable to get local issuer certificate”.** Windows can download a missing intermediate; most other clients cannot. Fix the server: [build the full chain file](https://pkizerotohero.com/guides/build-fullchain/) and see [verify error 21](https://pkizerotohero.com/errors/openssl-verify-error-21/).
- **`curl.exe` reports `CRYPT_E_NO_REVOCATION_CHECK` or `CRYPT_E_REVOCATION_OFFLINE`** (with `--cacert`: `schannel: the revocation status is unknown`). `curl.exe` asks Windows to check revocation, and your CA’s certificates point to a CRL that clients cannot reach, or to none. Publish the CRL where clients can fetch it ([revocation](https://pkizerotohero.com/handbook/revocation/)). Turning the check off hides the problem.
- **The name does not match.** Trusting the root does not fix [`NET::ERR_CERT_COMMON_NAME_INVALID`](https://pkizerotohero.com/errors/chrome-err-cert-common-name-invalid/): the server certificate needs the name in its [Subject Alternative Name](https://pkizerotohero.com/handbook/glossary/#subject-alternative-name).
- **Group Policy has not arrived.** Run `gpupdate /force`, then `gpresult /r` to see which GPOs applied.

Warning

Remove roots you no longer need

A retired or test root keeps vouching for any name until you delete it. Remove it with `Get-ChildItem Cert:\LocalMachine\Root\<thumbprint> | Remove-Item` or `certutil -delstore Root <serial number>`, or remove it from the GPO or Intune profile. Prefer a private CA whose certificates carry [name constraints](https://pkizerotohero.com/handbook/glossary/#name-constraints), so that it can only vouch for your own domains.

## Why this works

When a program asks Windows to check a server certificate, Windows builds a [certificate chain](https://pkizerotohero.com/handbook/glossary/#certificate-chain) up through the intermediates and accepts it only if it ends at a certificate in a Trusted Root store. The computer store applies to every account on the machine. Being self-signed does not make your root trustworthy; being in the store does ([Who do we trust?](https://pkizerotohero.com/handbook/trust-stores/)). How the chain is built and checked is in [Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/), and how to design a private CA that is safe to trust is in [A CA of your own](https://pkizerotohero.com/handbook/private-ca/).

## Go deeper

- [Import-Certificate](https://learn.microsoft.com/en-us/powershell/module/pki/import-certificate): the PowerShell cmdlet and its store paths.
- [certutil](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil): `-addstore`, `-delstore`, `-verify`, `-dspublish` and every option.
- [Distribute certificates with Group Policy](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/distribute-certificates-to-client-computers-by-using-group-policy): Microsoft’s step-by-step procedure.
- [Intune trusted certificate profiles](https://learn.microsoft.com/en-us/intune/device-configuration/certificates/trusted-root-profiles): fleet rollout, including the destination stores.
- [Chrome Root Store FAQ](https://chromium.googlesource.com/chromium/src/+/main/net/data/ssl/chrome_root_store/faq.md): which Windows stores Chrome reads for local trust.
- [Node.js `--use-system-ca`](https://nodejs.org/api/cli.html#--use-system-ca): which Windows stores Node.js reads.

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/guides/add-root-ca-windows/).

Last reviewed 20 October 2026Edition 0.9

## Keep going

### Learn why it works

- [Chapter 12: Who do we trust? CAs, trust stores and self-signed certificates](https://pkizerotohero.com/handbook/trust-stores/)
- [Chapter 22: A CA of your own: private two-tier PKI](https://pkizerotohero.com/handbook/private-ca/)
- [Chapter 13: Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/)

### Error pages

- [NET::ERR\_CERT\_AUTHORITY\_INVALID](https://pkizerotohero.com/errors/chrome-err-cert-authority-invalid/)
- [The remote certificate is invalid according to the validation procedure](https://pkizerotohero.com/errors/dotnet-remote-certificate-invalid/)
- [Could not establish trust relationship for the SSL/TLS secure channel](https://pkizerotohero.com/errors/powershell-could-not-establish-trust/)
- [schannel: SEC\_E\_UNTRUSTED\_ROOT (0x80090325)](https://pkizerotohero.com/errors/git-schannel-sec-e-untrusted-root/)
- [SEC\_ERROR\_UNKNOWN\_ISSUER](https://pkizerotohero.com/errors/firefox-sec-error-unknown-issuer/)

### Tools

- [Certificate decoder](https://pkizerotohero.com/tools/decoder/): Paste a PEM certificate and read every field in plain words.
- [Chain checker](https://pkizerotohero.com/tools/chain/): Paste a chain and see which link is missing, expired or out of order.

### Topics

- [Chains and trust stores](https://pkizerotohero.com/topics/chains-and-trust/)
- [Private PKI](https://pkizerotohero.com/topics/private-pki/)

## More guides: Trust a CA

- [How to work behind a TLS-inspecting corporate proxy, safely](https://pkizerotohero.com/guides/corporate-proxy-certificates/)
- [How to trust a private root CA on macOS](https://pkizerotohero.com/guides/add-root-ca-macos/)
- [How to trust a private root CA on Linux](https://pkizerotohero.com/guides/add-root-ca-linux/)
- [How to add a CA to a Java trust store (cacerts)](https://pkizerotohero.com/guides/add-root-ca-java/)
- [How to make Python, Node.js and npm trust a private CA](https://pkizerotohero.com/guides/trust-ca-python-node/)
