TrustKit-Android adds pinning and failure reporting to older Android releases
Easy SSL pinning validation and reporting for Android.
At a glance
- What is it?
- TrustKit Android is a small Java library that backports the Network Security Configuration pinning and debug override features to API 17 and adds report URIs for pinning failures. It runs on API 16 with its functionality disabled, and the last release was in 2026.
- Who is it for?
- Adopt TrustKit-Android when your app still supports Android versions before N and you need pinning plus a signal about pinning failures. Skip it if your minimum SDK is already 24 or above, because the platform's own network security configuration does the pinning without a library, and if you cannot accept a dependency that only shipped one release in six years.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 58 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Pinning on a platform that did not have it
TrustKit Android is a Java library for SSL public key pinning in Android apps, and the reason it exists is a version boundary. Android N introduced the Network Security Configuration, and with it the `<pin-set>` element and `<debug-overrides>`. Before N, an app that wanted pinning had no declarative mechanism, so developers either shipped their own TrustManager or pinned nothing at all. TrustKit fills that gap by extending the Network Security Configuration format and implementing the pinning and debug override behaviour itself on older releases, down to API level 17. The stated benefit is that an app supporting older Android versions can implement pinning in a future-proof way, using the same policy file it would use on N. The project states that TrustKit also runs on API level 16 for better compatibility, but that its functionality is disabled there, which is a fair summary of the whole library in one sentence.
Reporting is the second half of the library
The other thing TrustKit adds is a reporting channel for pinning failures, and this is the piece that distinguishes it from a pure backport. When validation of a pin fails for a specific connection, the library can send a report, and the report format is similar to the report-uri feature of HTTP Public Key Pinning and to the iOS version of TrustKit. In practice that means a mobile app can tell its operators that a specific host failed pinning, which is the kind of signal that distinguishes a broken certificate rotation from an interception attempt. Reporting is optional and configurable. The `TrustKitOptions` class can replace the built-in default report location, and the documentation gives the reason: a report service may require authentication or other request metadata. The iOS sibling is the reference implementation here, and the iOS version was first released at Black Hat USA 2015.
The policy lives in a network security config file
The pinning policy is a normal Android network security configuration file with a TrustKit-specific element added. You put it in `res/xml/network_security_config.xml`, declare a domain, list the pins, and add a `trustkit-config` block with the enforcement flag and the report URI. The debug overrides block lets you install a debug CA and override pins while developing.
<network-security-config>
<domain-config>
<domain>www.datatheorem.com</domain>
<pin-set>
<pin digest="SHA-256">k3XnEYQCK79AtL9GYnT/nyhsabas03V+bhRQYHQbpXU=</pin>
<pin digest="SHA-256">2kOi4HdYYsvTR1sTIR7RHwlf2SescTrpza9ZrWy7poQ=</pin>
</pin-set>
<trustkit-config enforcePinning="false">
<report-uri>http://report.datatheorem.com/log_report</report-uri>
</trustkit-config>
</domain-config>
<debug-overrides>
<trust-anchors>
<certificates overridePins="true" src="@raw/debugca" />
</trust-anchors>
</debug-overrides>
</network-security-config>The same file is then pointed at from the manifest, which is what enables the configuration as the app's network security configuration on Android N.
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>Because the file is the Android N format, an app can keep one policy across old and new releases, which is the future-proofing the documentation claims.
Wiring the socket factory into your HTTP client
The library is added as a normal Gradle dependency, declared in the project build.gradle as `implementation 'com.datatheorem.android.trustkit:trustkit:<last_version>'`. Initialisation takes the same resource path that the manifest already references, and the code comments note that TrustKit cannot be initialized twice, so you use either the default path or a custom resource, not both. After that you obtain an SSL socket factory and hand it to the HTTP client you use. The sample shows the four variants: a plain `HttpsURLConnection`, OkHttp 2.x, OkHttp 3.0 to 3.2, and OkHttp 3.3 and higher. The last group needs a trust manager as well as the socket factory.
// HttpsUrlConnection
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname)); // OkHttp 3.3.x and higher
OkHttpClient client =
new OkHttpClient.Builder()
.sslSocketFactory(OkHttp3Helper.getSSLSocketFactory(), OkHttp3Helper.getTrustManager())
.addInterceptor(OkHttp3Helper.getPinningInterceptor())
.followRedirects(false)
.followSslRedirects(false)
.build();A separate detail that catches people out: the OkHttp helpers pin per hostname, so the socket factory is asked for the server hostname rather than applied globally, and the interceptor is what enforces the policy on the request path.
Receiving the pinning failure report in the app
Reports are delivered as local broadcasts, and the sample registers a receiver to listen for them. The broadcast action comes from `BackgroundReporter.REPORT_VALIDATION_EVENT`, and the payload is a serializable `PinningFailureReport` carried under `BackgroundReporter.EXTRA_REPORT`.
class PinningFailureReportBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
PinningFailureReport report = (PinningFailureReport) intent.getSerializableExtra(BackgroundReporter.EXTRA_REPORT);
}
}That is the whole in-app path: register the receiver, read the report, do what you want with it. The alternative to shipping a report to a remote endpoint is exactly this, an in-process broadcast that a telemetry component or a crash reporter can pick up. The choice between the two is a policy decision, and the documentation leaves it open, which is the right call since a pinning failure report is sensitive information about your own infrastructure.
One release in six years is the upgrade risk
The release history is the thing to weigh before adopting. The listed releases are 1.1.5 on 2026-08-17, then 1.1.3 on 2020-04-30 and 1.1.2 on 2019-06-09, and the last push to the repository was on 2026-08-26. So the gap between the 2020 release and the 2026 one is close to six years, which tells you this is a library that was largely dormant and has recently been touched again. That has two consequences. First, the API surface described in the README is broad, with helpers for OkHttp 2.x, OkHttp 3.0 to 3.2 and OkHttp 3.3 and higher, and support for `HttpsURLConnection`, and a decade of Android versions in the compatibility range, so a modern project may find itself in a branch of the sample that has not been exercised in years. Second, the library targets `android-arsenal` API 16 compatibility, and the project publishes an API documentation site and a getting started guide rather than an inline reference, so expect to read the docs rather than the README to get the details right.
What pinning buys and what it cannot
It is worth being clear about the scope of the mechanism, because the library does not change what pinning protects against. Pinning binds a connection to a key rather than to a certificate authority, so it removes the trust-on-first-use weakness of certificate validation for the domains you configure. TrustKit does not extend that protection to domains you did not list, and the policy is enforced per domain and per hostname. The failure mode worth planning for is operational rather than cryptographic: pinning breaks when a server rotates its key and the app ships without the new pin, and the documentation here gives you no tooling for that, no pin expiry mechanism and no staged rollout. The `enforcePinning` flag and the debug overrides exist to soften this during development, with `overridePins="true"` letting a debug CA bypass the pins, and both are controlled from the same file. A team shipping a pinned app on a long support cycle should plan the key rotation process before it needs it, because the library will not do it for you.
Editorial conclusion
Adopt TrustKit-Android when your app still supports Android versions before N and you need pinning plus a signal about pinning failures. Skip it if your minimum SDK is already 24 or above, because the platform's own network security configuration does the pinning without a library, and if you cannot accept a dependency that only shipped one release in six years. Before you commit, confirm that version 1.1.5 builds against your Gradle and OkHttp versions, and read the getting started guide, since the README leaves the initialisation rules to that document.
Frequently asked questions
What Android versions does TrustKit Android support?
It backports the network security configuration pinning features to API level 17. It also runs on API level 16 for compatibility, but the documentation says its functionality is disabled there.
How do I add TrustKit to an Android project?
Add the Gradle dependency `implementation 'com.datatheorem.android.trustkit:trustkit:<last_version>'`, then initialise the library with `TrustKit.initializeWithNetworkSecurityConfiguration(this)` or with your own resource. It cannot be initialized twice.
How does TrustKit report pinning failures?
You add a report URI in the `trustkit-config` element of the network security configuration, and reports use a format similar to the report-uri feature of HTTP Public Key Pinning. In the app, failures arrive as local broadcasts carrying a `PinningFailureReport`.
Can TrustKit use a custom report server with authentication?
Yes. `TrustKitOptions` can replace the built-in default report location, which the documentation says is useful when the report service requires authentication or other request metadata.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/datatheorem-trustkit-android)Was this useful?