If you run git clone https://... on a stock Mac today, Apple's git still trusts certificates signed with the compromised eMudhra intermediate CA keys, keys that anyone can recover from the public certificates. Firefox and Chrome blocked those certificates on 17 October. Safari followed. /usr/bin/git did not, and as of 28 October it still trusts them.
Then macOS 27.2 shipped on 26 October without a fix, and the update undid the /etc/ssl/cert.pem workaround people had already applied. If you patched your Mac last week, check again.
Checking your own machine takes about a minute, and the fix I use is further down. Skip the Keychain advice that's going around; it doesn't help here. Homebrew git also turned out not to be the escape hatch people assumed.
What happened with the eMudhra intermediate CAs
eMudhra generated the private keys for eight intermediate CA certificates so badly that the keys can be recovered from the certificates themselves. That has been possible since the certificates were issued in April 2025. On 17 October the researcher who reported it signed a test message with each of the eight keys and sent the results to the root programs. One HN commenter claimed that one of the private keys is literally 4.
Per Apple's support note, six of the eight issue TLS certificates: EM EV, OV and DV TLS CA - G3B and G3C. Each exists twice, once under emSign Root TLS CA - G3 (chaining to emSign ECC Root CA - G3) and once cross-signed by Sectigo under AAA Certificate Services. That makes 12 certificates, and Apple's own wording is that someone holding these keys "could create certificates that appear valid for any website."
The timeline, from the incident page and Apple's note:
| Date (2026) | Who | Status |
|---|---|---|
| 17 Oct | Firefox, Chrome | Blocked |
| 19 Oct | Apple frameworks (Safari, Mail, apps on Apple's networking stack) | Blocked |
| 20 Oct | Microsoft | Blocked |
| 26 Oct | macOS 27.2 | No fix, reverts manual workaround |
| 28 Oct | Apple's git, curl, python3
|
Still trusting |
Homebrew, Debian, Ubuntu, Fedora, Arch, Alpine, Go, Node.js, Python certifi, Git for Windows, GitHub CLI and dozens of other projects shipped fixes in the meantime, many of them run by volunteers.
Why the browser fix didn't reach your terminal
Apple's note is blunt about it: command-line tools "(including curl, git, python3, ruby, perl, and openssl)" check certificates against /etc/ssl/cert.pem, and for certificates that chain to a root in that file, "these tools don't check Apple's block or whether the certificate has been revoked."
cert.pem contains roots only. The compromised certificates are intermediates, and the roots above them (emSign ECC Root CA - G3 and AAA Certificate Services) were never compromised. A tool that checks no revocation and enforces no Certificate Transparency sees a chain ending at a trusted root and accepts it. Browsers that enforce CT were never really exposed, because no CT log entries exist for these intermediates. curl doesn't enforce CT, and neither does the git built on it.
That's also why the Keychain advice going around doesn't help. security find-certificate -a -c eMudhra only lists what's in the Keychain, and marking certificates as "Never Trust" in Keychain Access changes the store Safari uses. Neither touches the flat file /usr/bin/git reads. One commenter ran find-certificate, found the eMudhra roots "still there", and was rightly told the roots were never the problem.
Check which git and which CA bundle you're using
First, which git:
which -a git
git --version
/usr/bin/git is Apple's shim into the Xcode Command Line Tools. /opt/homebrew/bin/git (or /usr/local/bin/git on Intel) is Homebrew's.
Then ask git which CA file it actually loads. This trick comes from Junian's write-up:
GIT_CURL_VERBOSE=1 git ls-remote https://github.com/git/git.git 2>&1 | grep -i "CAfile"
git config --show-origin --get http.sslCAInfo
If you see CAfile: /etc/ssl/cert.pem and no http.sslCAInfo override, you're on the vulnerable bundle.
Finally, the real test. The incident site runs a server using one of the compromised intermediates:
git ls-remote https://git-emudhra.we-have-a-problem.com/check.git
A certificate error means you're protected. A listed commit means you aren't. For curl:
curl https://dv-g3b-noct-emudhra.we-have-a-problem.com/
curl https://dv-g3b-aaa-noct-emudhra.we-have-a-problem.com/
The second host goes through the Sectigo cross-sign. If the first fails and the second connects, you removed one root and not the other.
If you want to see what an attack looks like, the incident page has a demo. Run it in a temporary directory:
git -c http.curloptResolve=github.com:443:15.235.19.186 clone https://fake-user@github.com/galadran/emudhra-git-test
The -c option points github.com at their test server for this one command. A patched git refuses with a certificate error. An unpatched one clones happily, and the README starts with INTERCEPTED. Keep the fake-user@ prefix, otherwise git would send your real GitHub credentials to the test server.
Homebrew git is not automatically safe
The obvious answer is "just use Homebrew git", and this week it was wrong. Homebrew's ca-certificates formula is patched, and a Homebrew maintainer initially said on HN that Homebrew's tools were fine because it ships its own bundle. Then users ran the check. /opt/homebrew/bin/git still reached the compromised host, and one commenter reported git 2.56.0 from Homebrew staying vulnerable until they patched the system file. The maintainer's reply: "I spoke too soon about Git being patched just because our own CA bundle was." Unlike Homebrew's curl, Homebrew's git had been defaulting to the system /etc/ssl/cert.pem, something the maintainer said "might indeed be an oversight" before adding that a fix was underway.
What matters is which bundle git loads, and you can't tell that from the path of the binary. Run the ls-remote check whatever which git says.
The fix: pin http.sslCAInfo to a patched bundle
This is the option I'd pick, because macOS updates don't overwrite ~/.gitconfig:
brew install ca-certificates
git config --global http.sslCAInfo "$(brew --prefix ca-certificates)/share/ca-certificates/cacert.pem"
git config --global --get http.sslCAInfo
git ls-remote https://git-emudhra.we-have-a-problem.com/check.git
The last command should now fail with an SSL error. On Apple Silicon the path resolves to /opt/homebrew/opt/ca-certificates/share/ca-certificates/cacert.pem. This applies to both Apple's and Homebrew's git, since both read the same global config. For a single shell or a CI job, export GIT_SSL_CAINFO=... with the same path works too.
The downside: this fixes git only. Apple's curl and python3 still read /etc/ssl/cert.pem, and the built-in pip3 uses its own outdated copy of the roots.
The fix Apple documents: edit /etc/ssl/cert.pem
To fix Apple's curl, git, python3 and the other tools that read /etc/ssl/cert.pem at once, remove the root. These commands come straight from the incident page, and Apple's note gives the same steps. Copy them exactly.
Back up:
[ -e /etc/ssl/cert.pem.orig ] || sudo cp -p /etc/ssl/cert.pem /etc/ssl/cert.pem.orig
Remove emSign ECC Root CA - G3:
t=$(mktemp) &&
awk -v s='=== /C=IN/OU=emSign PKI/O=eMudhra Technologies Limited/CN=emSign ECC Root CA - G3' \
'/^(===|###) /{skip=0} $0==s{skip=1} !skip' /etc/ssl/cert.pem > "$t" &&
[ -s "$t" ] && sudo install -m 0644 -o root -g wheel "$t" /etc/ssl/cert.pem; rm -f "$t"
Optionally, remove AAA Certificate Services. This blocks the six Sectigo cross-signs, but it can break unrelated sites that still chain to that root:
t=$(mktemp) &&
awk -v s='=== /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services' \
'/^(===|###) /{skip=0} $0==s{skip=1} !skip' /etc/ssl/cert.pem > "$t" &&
[ -s "$t" ] && sudo install -m 0644 -o root -g wheel "$t" /etc/ssl/cert.pem; rm -f "$t"
Verify. If both roots are gone, this prints nothing:
openssl crl2pkcs7 -nocrl -certfile /etc/ssl/cert.pem | openssl pkcs7 -print_certs -noout |
grep -E 'emSign ECC Root CA - G3|AAA Certificate Services'
Apple warns that a macOS update can replace this file, and 27.2 already did exactly that. If the verify command lists a root again after an update, delete the stale .orig backup and repeat the steps. I put the verify line in a shell alias so I remember to run it after every update.
The built-in pip3 ignores this file; the incident page has a separate sitecustomize.py step that points it at /etc/ssl/cert.pem.
My setup is both: http.sslCAInfo for git, because it survives updates, plus the cert.pem edit for everything else.
If you run macOS CI runners
Self-hosted and cloud macOS runners ship the same /etc/ssl/cert.pem, and as the Homebrew episode showed, git can end up reading it even when it isn't /usr/bin/git. Every git clone over HTTPS in a build job is a place where an attacker on the network path can hand you code they chose, or grab the token in the URL. Add GIT_SSL_CAINFO to the job environment, or run the ls-remote check as a pre-step that fails the build.
What I make of Apple's response
Apple's frameworks blocked the certificates within days, and the support note is unusually honest. But dozens of other projects, many run by volunteers, had fixed their CA bundles days earlier, while Apple shipped a point release that put the vulnerable roots back. I can't defend that 27.2 release, given that the people running git push in Terminal are exactly the people whose credentials lead to supply-chain attacks.
Which git does which git print on your machine, and did you know Apple's and Homebrew's git could end up reading the same CA file? If you've found a cleaner fix that survives macOS updates, put it in the comments.
Sources
- Apple's git still trusts the compromised eMudhra certificates
- eMudhra incident page with workarounds
- Apple: About the compromised eMudhra intermediate CAs
- Hacker News discussion (Apple's git)
- Hacker News discussion (Apple support note)
- Lobsters discussion
- Using git on Mac with a custom CA cert (Junian)
Top comments (0)