⚠️ PHP2Shell: Two Critical PHP Flaws Put Mobile Backends at Risk ⚠️ PHP2Shell: Two Critical PHP Flaws Put Mobile Backends at Risk See What to Check →

Certificate Pinning for Mobile Apps: Lessons from the eMudhra CA Incident

Share

TL;DR

  • In April 2025, eMudhra, a certificate authority (CA), issued eight intermediate certificates whose private keys were tiny numbers, not 384-bit random values. Anyone could derive them from the public certificate. The flaw went undiscovered until October 2026.
  • Your browser and phone treat every trusted CA the same, and the certificates were cross-signed by a major CA. That made them trusted by devices that never trusted eMudhra.
  • Mobile apps can narrow trust by pinning the root CAs they have already vetted. Pinning roots still lets you rotate endpoint certificates without breaking shipped apps.
  • CRL, OCSP and Certificate Transparency would not have helped during the 18 months before discovery. Narrowing your trust anchors would have.
Phone with an Android security shield beside a cracked certificate with a red warning, illustrating the eMudhra CA incident

What happened in the eMudhra CA incident?

On April 30, 2025, eMudhra, a certificate authority (CA), generated a batch of 24 intermediate certificates. Eight of them had a critical issue that went undiscovered until October 2026. Six were to be used for websites and two for code signing.1

The private keys for these were supposed to be 384-bit random numbers. In this case, the numbers were 4, 56, 66, 115, 155, 156, 230 and 237. Those are not 384-bit values. Each one fits in a single byte. No stretching of the definition of "randomness" would cover that. Anyone could derive these keys from the public certificate.2

Before you discard this as a niche CA problem, consider the following:

  • The CA in question has been operating since 2008.
  • They've since issued over 60 million certificates.3
  • The trust store in your browser, phone or vehicle does not differentiate between "niche regional CA" and "big global CA."
  • The certificates were cross-signed by another CA, making them trusted by devices that never trusted the eMudhra CA to begin with.4
  • The cross-signing was done by the third-largest CA by share of all websites.5

Once the CA is in the trust store, it is treated the same as all other CAs in it. Today, 75 unique root CA owners are trusted by major trust stores (Microsoft, Mozilla, Chrome, Apple), 37 of which are trusted by all four.6

For general-purpose software like your browser, trusting dozens of CAs is a practical necessity: it needs to connect to arbitrary websites across the internet.

Your mobile app, on the other hand, likely only connects to a handful of known endpoints. It doesn't need to trust the entire internet's worth of CAs. There is a well-known but consistently misunderstood tool to reduce this risk: certificate pinning.

Fail-Closed: Certificate Pinning

In the most often understood sense, certificate pinning is hard-coding your endpoint certificate's Subject Public Key Info (SPKI) hash into your app.

But in the broader sense, certificate pinning is just a narrowing of the trust store, and you are in full control of how granular you want that narrowing to be. Either way, pinning fails closed: the app refuses any certificate outside the set you chose.7

A trust store is the collection of the certificates you trust. Because some certificates, or more accurately, their keys, can be used to sign others, you end up with a chain of trust, with some certificates at the root of it. The entire system is known as PKI (Public Key Infrastructure), and the certificates at the root are the root of trust, known as trust roots or root CAs.

Your browser trusts dozens of root CAs, each of which can issue certificates directly or through intermediate CAs. Your browser will trust any certificate that chains back to one of those roots, provided the chain is valid.

If you haven't taken action to override the defaults, your app will rely on the trust store maintained by the OS. But unless your app is as broadly scoped as a browser, it does not have to: it likely only connects to a handful of endpoints. There is no need to trust the same extensive set of CAs.

The knee-jerk reaction then is to make the app trust only the (leaf) certificates used by these endpoints. But that comes with a complex network of practical issues when these endpoints update, revoke or change their certificates. Copies of your app already installed on users' devices will become unable to talk to their backends when the certificates presented by these endpoints change. Until users upgrade, the app does not know about the new certificates.

It is becoming more and more common for me to have to open the Play Store and download an app update every time I want to order a pizza. That is least acceptable for the apps with the highest risk profile, the ones that would be most interested in narrowing the trust store: banking and healthcare.

However, not all is doom and gloom. Your organization (hopefully) vetted the CA when obtaining the TLS certificates for your endpoints. Often big organizations use more than one CA and obtain more than one certificate per endpoint for redundancy.

So you don't pin the endpoint certificates. You pin your vetted root certificates instead. This way you solve the problem 80/20 style:

  • You narrow the trust scope to the CAs you have already de facto trusted, limiting exposure to other CAs misbehaving or getting compromised.
  • You can renew or replace endpoint certificates without breaking the app, as long as they chain back to one of your trusted CAs.

For implementation detail, see NowSecure's guides to Network Security Configuration in Android and certificate pinning for Android and iOS.

Other Mitigations

Certificate compromise is not a new issue in cybersecurity. Over time, the industry has developed multiple crutches for this eventuality:

  • Certificate Revocation Lists (CRL)
  • Online Certificate Status Protocol (OCSP)
  • Certificate Transparency (CT) logs

However, in practice, these either fail open or are not enabled at all in most cases on Android.

Certificate Revocation Lists

CRLs have unfortunate properties:

  • there are multiple sources to query
  • the lists are not tiny
  • in order to be useful, the lists need to be up to date on the network stack of the side initiating the connection (app, device, browser or OS)

So it's multiple sequential races:

  1. The compromise of the certificate needs to be discovered (18 months with eMudhra)
  2. The revocation event needs to occur
  3. The connection initiator needs to learn about the revocation before an attacker can exploit the compromised certificate

Does OCSP Stop an Attacker in the Middle?

No. OCSP is a protocol meant to enable checking the revocation status in real time.

Unfortunately, if the attacker is in the middle between the client and the server to intercept the traffic, the attacker is also in the position needed to block OCSP queries, and they fail open ¯\_(ツ)_/¯8

Certificate Transparency

They're gonna know. How would they know?

The latest hot thing enabled by default in Android 17 is Certificate Transparency (CT) enforcement. But it only achieves the goal if you take extra steps outside of the mobile app.

The idea is to fail closed if a given certificate does not validate against CT logs. CAs and others append to these logs when they issue certificates. The actual implementation is a little more involved; it includes signed certificate timestamps (SCT) and handshakes, which we will omit for our purposes here.

You know which certificates for your endpoints you have actually requested. Therefore, if someone appends a valid certificate for your endpoints, one which you did not request, you will know there is a problem.

Notice the catch? There are two:

  1. If the attacker appends their generated certificate to the CT log, the connection will not be rejected, and they will successfully compromise the victim
  2. You will only become aware of the new certificate if you monitor the CT logs for your endpoints and ring the alarm upon seeing the impostor certificate there

Your customer still gets compromised. Unless you or someone else is monitoring the CT logs and immediately taking action, you have gained nothing. You still need to work with the CA to revoke the bogus certificate. The CA needs to deal with the breach. You need to migrate to a new non-compromised trust root. The work does not stop there.

Although the concept is ancient in tech timelines,9 its widespread adoption is a very current subject: Android only made it enabled by default beginning last June for apps targeting Android 17 (June 16, 2026), running on Android 17 devices. You can opt in earlier.10

What Would Have Protected Apps During the eMudhra Incident?

Narrowing your trust anchors would have protected apps. The other mitigations would not have.

In the eMudhra incident, the CA revoked the affected certificates within a day. The major vendors distrusted the CA within three days of discovery. Discovery took 18 months. During those 18 months, none of the "other mitigations" above would have been effective, because they all come into play after discovery.

If you had narrowed your trust anchors to exclude the CA involved in the incident and the cross-signing CA, you could have slept through your alarm safely on that day.

Want to know how your mobile app handles certificate trust? NowSecure Platform reports certificate pinning status in your mobile apps automatically. For a deeper check, NowSecure Mobile PTaaS adds expert manual testing.

References

  1. https://bugzilla.mozilla.org/show_bug.cgi?id=2083449#c5
  2. https://scotthelme.co.uk/eight-bits-of-trust-emudhras-ca-keys-cracked-in-milliseconds/#i-checked
  3. https://emudhra.com/en/our-history
  4. https://bugzilla.mozilla.org/show_bug.cgi?id=2083449#c6
  5. https://my-ssl.com/learn/top-10-ssl-cas#tf-title
  6. https://my-ssl.com/learn/top-10-ssl-cas#largest
  7. Fail-closed, also known as fail-secure, is a design where the system falls back to blocking access or stopping operation when a failure or error occurs. Fail-open, on the contrary, defaults to not restricting access, and is effectively an optional check under error conditions.
  8. https://www.imperialviolet.org/2012/02/05/crlsets.html
  9. https://www.rfc-editor.org/info/rfc6962/
  10. https://developer.android.com/about/versions/17/behavior-changes-17#ct-default
Georgi Boiko

About the Author

Georgi Boiko

Senior Research Engineer

See what NowSecure Agentic AI surfaces in your mobile app portfolio.

Start with your highest-priority apps. See what AI surfaces from day one.

Union

Frequently asked questions

Have more questions? Get in touch with our team.