Member-only story
Android Security: Enabling Certificate Transparency checks in WebViews

When I first released my open-source certificate transparency library for Android and the JVM, I provided mechanisms to cover the majority of network connections, namely OkHttp, HttpURLConnection and Volley. However, there was no support for Android WebViews.
If you want to learn more about certificate transparency, read Android Security: Certificate Transparency.
In this article, we explore the issues surrounding WebView support. We look at how to overcome this to implement certificate transparency checks in WebViews with a single line of code (and a bit of magic in the library):
installCertificateTransparencyProvider()
The Problem with WebViews
The Status of Certificate Transparency in Android Webview makes it seem unlikely WebViews will have certificate transparency checks enabled any time soon, regardless of the support built into Chromium.
We need to find a way to perform these checks by intercepting the SSL handshaking of all the network connections and terminating if necessary.
However, on the surface, with WebViews, this doesn’t seem possible. The best you can hope for is to override shouldInterceptRequest
in a WebViewClient
, which only allows you to handle GET requests, there is no access to the body of POST requests. If you were to go down this route, you would make the network calls yourself using something like OkHttp and certificate transparency checks could then be enabled with the libraries OkHttp network interceptor.
TrustManager factories
Fortunately, there is a lower-level way to intercept the SSL handshaking process, even in WebViews.
Under the hood making a secure network connection uses an X509TrustManager
and an SSLSocketFactory
. It is the X509TrustManager
that performs checks on the SSL certificates of the connection. We can use this to add additional certificate transparency checks.
A typical implementation might look like the following; indeed, this matches the defaults in OkHttp:
val trustManagerFactory = TrustManagerFactory.getInstance(…