Any HTTPS-using tool inside MSYS2 — pacman -Sy, curl, wget, git clone, pip install — fails with SSL/certificate verification errors on a machine behind Zscaler. The cause is TLS interception: Zscaler decrypts every HTTPS connection and re-encrypts it with its own root CA. Windows trusts that CA (Zscaler installs it), but MSYS2 ships its own CA bundle that has never heard of it, so every connection fails to verify. The fix is one and the same for all of them — get the Zscaler root cert out of the Windows trust store and into MSYS2's. pacman is just the usual first thing to break.

1. Export the Zscaler root cert from Windows

Zscaler installs its root into the Windows Trusted Root Certification Authorities store. Pull it from there.

GUI route:

  1. Run certmgr.msc
  2. Trusted Root Certification Authorities → Certificates
  3. Find Zscaler Root CA (it may be named "Zscaler Intermediate Root CA" or similar)
  4. Right-click → All Tasks → Export
  5. Choose Base-64 encoded X.509 (.CER) — this is PEM, which is what MSYS2 wants
  6. Save it as zscaler.crt

PowerShell route (exports whatever Zscaler certs are present — usually a root and an intermediate):

Get-ChildItem Cert:\LocalMachine\Root |
  Where-Object { $_.Subject -like "*Zscaler*" } |
  ForEach-Object { Export-Certificate -Cert $_ -FilePath "$env:USERPROFILE\zscaler-$($_.Thumbprint).cer" }

Note the $($_.Thumbprint) in the filename: if Where-Object matches both the root and the intermediate, giving each cert a unique name keeps them from clobbering each other — a fixed filename would leave you with only the last one.

Export-Certificate writes DER, not PEM (which is what MSYS2's trust store wants). Convert it right there in PowerShell with the built-in certutil — no openssl, and no switching shells:

certutil -encode .\zscaler-<thumbprint>.cer zscaler.crt

certutil -encode produces Base-64 PEM — convert each cert if you exported more than one. The file you install must be PEM: it should start with -----BEGIN CERTIFICATE-----. (The GUI route's "Base-64 encoded X.509" export already gives you PEM, so it skips this step entirely.)

2. Install it into MSYS2's CA trust

MSYS2 keeps its trust anchors in /etc/pki/ca-trust/source/anchors/, and update-ca-trust merges everything there into the system trust store that pacman and curl read. That directory plus update-ca-trust is the whole interface — drop the cert in and regenerate:

cp /c/Users/<you>/Desktop/zscaler.crt /etc/pki/ca-trust/source/anchors/zscaler.crt
update-ca-trust

update-ca-trust rebuilds the system trust store from the anchors. This is the persistent method — it survives ca-certificates upgrades because the source cert lives in the anchors directory and gets re-merged on every rebuild. Drop the cert in, run the command, done.

3. Verify

pacman -Sy

If it syncs the databases without cert errors, you're done.

This also fixes curl and wget

The same update-ca-trust rebuild fixes more than pacman. curl and wget in MSYS2 use the same system trust store, so once it's regenerated they verify Zscaler-inspected HTTPS with no extra configuration — no -k, no --no-check-certificate, no per-command env var. If curl https://… or wget https://… was failing with cert errors before, it just works after step 2.

To test, hit the dedicated plaintext check endpoint on this site rather than a random third party — it returns an "IT WORKED" banner plus the request as the server saw it (your IP, protocol, User-Agent). Reaching it with a 200 over a verified cert is the proof:

curl https://www.cmunroe.us/check          # human-readable banner + client details
curl https://www.cmunroe.us/check?json     # machine-readable JSON, for scripting
wget -qO- https://www.cmunroe.us/check      # same, via wget

If any of those print the banner instead of a TLS/certificate error, your CA trust and proxy path are working.