psf-emudhra-mitigate(8)
eMudhra intermediate CA compromise, mitigation (v1)
Disclosed 20 Oct 2026: https://emudhra.we-have-a-problem.com/
If this software is helpful, consider a donation to our 501c3 nonprofit:
https://privacysafe.foundation
The private keys of eight eMudhra intermediate CAs can be recovered from
their certificates. Browsers block them through OneCRL, CRLite and CRLSets,
but the system CA store, and everything that reads it (OpenSSL, GnuTLS, curl,
wget, apt, git, Python, PHP, Go, Ruby, Java via ca-certificates-java), keeps
trusting them until ca-certificates is updated. This script distrusts the
roots that anchor them and then proves the store rejects all of them.
Usage:
./emudhra-mitigate.sh [command] [--force] [--ignore-env]
check environment report only; changes nothing, root optional
(exit 0 = ok, 1 = hard blocker, 2 = needs --ignore-env)
apply (default) distrust the affected certificates in the system store,
rebuild it, fix the Java keystore, and verify
status mitigation state, store tests and stale processes
restore undo everything this script distrusted (re-exposes you
if ca-certificates isn't patched)
cleanup once ca-certificates is patched: remove this script's
distrust, but only if the store still rejects every
compromised intermediate afterwards (--force skips the
patch check, never the store test)
version print the script version and exit
--ignore-env proceed past soft environment blockers (a running
process or system-wide override uses a CA store this run
can't fix). Hard blockers (non-Debian, no
update-ca-certificates, no openssl, not root) can't be
overridden.
Every command first checks, in order: OS (Debian, Ubuntu, Trisquel and
popular derivatives), the system CA store and its package, other CA stores
(Java, Python certifi and other bundles, Node.js, NSS, overrides), then system
(root, container, tools). The system store's patch state is reported from
three signals: the fixed build for your release, extra FIXED_BUILDS, and the
package changelog. The verdict that matters is functional: every command
tests each store against the 16 published intermediate certificates, which
are embedded below and checked against their published SHA-256 fingerprints.
Env overrides:
FIXED_BUILDS="20250419~deb12u2" extra fixed ca-certificates builds
SCAN_PATHS="/opt /srv ..." where to look for bundled CA files;
empty disables the scan
SCAN_DEPTH=9 find -maxdepth for that scan
TEST_HOSTS="api.example.com:443" hosts to TLS-test before and after
apply, to catch collateral breakage
JAVA_STOREPASS=changeit Java keystore password
Debian/Ubuntu/Trisquel layout: /etc/ca-certificates.conf and
update-ca-certificates. A "!" line in that file survives package upgrades
(the ca-certificates postinst and debconf config keep deselected entries).
PSF_LOCK_WAIT seconds a run that changes the host waits for another one that is already
changing it (default 30), then stops with exit 2; the lock is STATE_DIR/.lockThe Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.