跪拜 Guibai
← Back to the summary

Guessable CA Keys: Why Flutter 3.47.8 Is a Mandatory Update

Should your Flutter project urgently upgrade to 3.47.8?

Hello everyone, I'm Lao Liu.

Today many friends forwarded to me the news that Flutter 3.47.8 fixes a certificate vulnerability, asking me whether their projects should upgrade immediately.

Seeing that the private keys can be guessed directly, it's normal to be nervous. But when we go back to the project, we still need to answer a few real-world questions. Is my App at risk? After upgrading, do I need to force users to update? My old project has many dependencies; can it upgrade stably?

This article explains the incident clearly, and then tells you how to judge whether your project should upgrade.


What happened?

In October 2026, a serious incident occurred in the HTTPS certificate trust system.

alt text

The Indian CA eMudhra issued 8 intermediate CA certificates, and their private keys were so weak they could be guessed directly. One of the private keys was the number 4.

Anyone who obtains these private keys can sign a seemingly legitimate HTTPS certificate for any domain, meaning your system's HTTPS verification would show that this is a real and reliable service. Currently, these certificates have been revoked.

Flutter subsequently released 3.47.8, with the corresponding Dart version 3.13.7. The reason is direct: Flutter's default TLS implementation does not use the revocation list that browsers and operating systems use.

How could the private keys be guessed?

According to Google's security blog and eMudhra's official statement, the timeline is as follows.

On April 30, 2025, eMudhra performed key generation operations in a FIPS 140-2 Level 3 hardware security module (HSM), batch-generating keys for 24 intermediate CAs.

The wrap/unwrap key export step in the script was written incorrectly, resulting in an additional set of weak backup keys being generated in the HSM. Because the key labels were similar, these weak keys were subsequently used to sign CSRs and submit to the browser root certificate programs.

On October 17, 2026, security researcher Wayne used 8 of the private keys to sign a message, and reported them together with the certificates to Apple, Chrome, Microsoft, and Mozilla, proving that he possessed the private keys.

On October 18, eMudhra revoked the 8 intermediate certificates.

On October 20, Chrome released CRLSet, Mozilla released OneCRL, and Apple and Microsoft followed. Chrome also announced it would remove the emSign ECC Root CA - G3 root certificate that issued these certificates from its root store, and push the update fully on October 27.

The actual values of these 8 private keys are 4, 56, 66, 115, 155, 156, 230, and 237.

Looking at this set of numbers, you can roughly understand how serious the problem is.

Why is a private key of 4 dangerous?

The private key of a P-384 elliptic curve is essentially a random integer (d) between 1 and (n), and the public key is (Q=d\times G), where (G) is a fixed base point.

Under normal circumstances, (d) has about (2^{384}) possibilities, so brute force enumeration is impractical.

This time it's completely different. The private keys are only 3 to 8 bits, so an attacker only needs to enumerate from 1 to 255, calculate (d\times G) for each, and compare with the public key in the certificate to reverse-engineer the private key. An ordinary laptop can do this in under a second; no special equipment is needed.

After the private key is leaked, an attacker can sign a *.yourbank.com certificate themselves, then construct a certificate chain like this:

Forged leaf certificate → eMudhra intermediate CA → root CA.

The client already trusts the root CA, so from the certificate chain verification perspective, this chain is completely valid.

A key defense played a role

Chrome, Firefox, Edge, and Safari require certificates to be entered into the Certificate Transparency log, also known as the CT log.

If an attacker signs a certificate secretly, once it enters the CT log it will be exposed; if it doesn't enter the CT log, the browser will directly reject it.

Google clearly stated that before the ban, these 6 TLS intermediate certificates did not sign any leaf certificates that entered the CT log. Therefore, for clients that enforce CT checks, the actual likelihood of being attacked is very low.

However, there is an element of luck here. Many non-browser clients, such as language runtimes, command-line tools, containers, and embedded devices, do not check CT and can only wait for their own updates.


Why does this affect Flutter?

Many people's intuition is that browsers and operating systems have added to the blacklist, so the problem should be solved.

For Flutter applications, this reasoning doesn't hold.

dart:io's TLS is implemented by Dart itself. Dart compiles BoringSSL into the runtime, and root certificates are also bundled with the SDK, sourced from the Mozilla root store, not the system trust chain.

It does not read Chrome's CRLSet, nor does it read the distrust list in Windows certificate store, or the revocation status in macOS keychain. By default, it also does not perform OCSP or CRL online revocation checks, nor does it enforce CT checks.

So a very awkward situation can occur.

Browsers and systems have already rejected forged certificates, but your Flutter App may still use the old root certificate copy, and HttpClient may still complete a TLS handshake normally.

In the Flutter ecosystem, package:http and dio both use dart:io by default, covering the vast majority of network requests. Even though the certificate has been revoked, Flutter is unaware of it.

Browser security does not mean your App is secure. The client uses a certain network stack; you have to check whether that network stack has been fixed.


What does Flutter 3.47.8 fix?

This fix mainly includes two parts.

First, it upgrades the built-in BoringSSL certificate blacklist, directly rejecting certificate chains that contain these intermediate CAs during the TLS handshake.

Second, on Android 14 and above, dart:io now loads system root certificates from the updatable Conscrypt APEX module.

The second part is a structural improvement. In the future, when Google pushes root certificate revocations through Play system updates, Apps will have a chance to get the fix without needing a re-release.

There's also a question: will Android systems in China sync the update? Most manufacturers should do so.


Should your project urgently upgrade?

Let me give my judgment first.

I am usually cautious about upgrading old projects, and particularly dislike touching the build chain and plugin dependencies just to chase new versions. But this time it involves TLS certificate trust, so the evaluation order should be reversed. First confirm the exposure surface, then decide the upgrade pace. The usual conservative version strategy does not apply to vulnerability-fix scenarios.

A typical attack requires first hijacking the network connection between the App and the server, then using the leaked CA private key to forge a certificate chain, making the App treat the forged server as the real one.

Therefore, when assessing risk, mainly look at two things.

Does the App have network requests that can be hijacked, and does it have server-side authentication mechanisms independent of the CA trust system? The number of access nodes and whether the communication protocol is public are not core judgment criteria.

You can handle it in the following three situations.

App accesses multiple public network services

Such projects usually involve different teams and third-party SDKs, and the cost of temporarily adding unified protection is high, so it is recommended to upgrade as soon as possible.

App only accesses its own server, and has additional authentication

If the client has pre-provisioned trusted public keys and strictly verifies server signatures, it can reduce some risk of forged responses.

But you still need to confirm the signature coverage, anti-replay mechanisms, and the confidentiality and integrity of data. You cannot simply conclude it is safe because the interface has a token or the response is signed.

App only accesses its own server, but has no additional authentication

Prioritize upgrading Flutter and re-releasing. If you cannot upgrade temporarily, you can evaluate temporary measures like certificate pinning or public key pinning. It is not advisable to hastily self-develop an authentication protocol to replace the official fix.

Teams can do a round of investigation today. List the Flutter and Dart versions used in production, the actual network stack, third-party SDKs integrated, and whether certificate pinning or server signature verification is in place. After this list is complete, the upgrade priority will be basically clear.


Upgrading the SDK only handles the first half

From the client perspective, upgrading the Flutter version is not the end.

You also need to consider how to handle App versions already running in production.

Upgrading the development branch to 3.47.8 only means the next package will have the fix. Old versions currently running on users' phones still have the old network stack and old certificate copy.

The project needs to combine risk level, user update ratio, and release cost to decide whether to use forced upgrade, risk warnings, or regular version iterations. For scenarios involving accounts, payments, or sensitive data, the server and client should also evaluate the disposal plan for old versions together.

The end of a security fix is the actual contraction of the exposure surface in production, not a local execution of flutter upgrade.


Which other clients need to follow up?

Client Type Status
Chrome / Firefox / Edge / Safari Already blocked via CRLSet / OneCRL / CRLite, basically safe
Windows / macOS / iOS system stack, including WKWebView, URLSession Apple, Microsoft have blocked
Android system stack + Google Play services Already updated via Play Services
Flutter / Dart (dart:io) Must upgrade to 3.47.8 / 3.13.7 and re-release
Go programs CVE-2026-111943, fixed in 1.27.3 / 1.26.10, affects Docker, K8s, Terraform
Electron apps, such as Slack, Discord, etc. Need to wait for Electron to release fix, then wait for app to follow
Java / Node / curl / container images / embedded devices Update CA bundle separately, otherwise continue to be exposed

One detail worth noting.

Among the 8 certificates, 2 are Microsoft code-signing certificates. This means the problem is not limited to HTTPS forgery; theoretically, it could also be used to forge signed Windows programs.

Additionally, these 8 public keys were cross-signed by Sectigo using the old Comodo AAA root. The same key has two trust paths, so both paths need to be revoked separately.

Going back to the original question, whether a Flutter project urgently needs to upgrade depends on your network exposure and existing protections. But there is one thing you can do right now: first check your production versions, network stack, and third-party SDKs, then arrange upgrade, regression, and release.

Don't let the upgrade stop on the development computer, and don't put off security fixes indefinitely just because an upgrade might bring regression risk.

What Flutter version is your project currently on? When evaluating the upgrade, is the sticking point plugin compatibility, release cost, or handling old versions in production? Welcome to share in the comments.

🤝 If you are interested in client-side or Flutter development, feel free to contact Lao Liu, we can learn from each other.

🎁 Private message to get Lao Liu's "Flutter Development Handbook" for free, covering 90% of app development scenarios. It can serve as a knowledge map for Flutter learning.

💬 : laoliu_dev

📂 Lao Liu also organizes his historical articles in a GitHub repository for easy reference.

🔗 https://github.com/lzt-code/blog