D
Chaos Proxy
Start Debugging
← Back to Blog
Android

How to Bypass SSL Certificate Validation in Android (OkHttp & Retrofit)

Updated January 2026 • 2 min read

🚨 DANGER: Do not use in Production!

Disabling SSL validation makes your app vulnerable to Man-in-the-Middle (MitM) attacks.Google Play will reject your app if you leave this code in your production build. Always wrap this code in if (BuildConfig.DEBUG) checks.

If you are using OkHttp (which Retrofit uses internally), you might encounter CertPathValidatorException when working with local dev servers or proxy tools like Charles or Debuggo. Here are the two ways to solve this: the "Dirty Way" (Code) and the "Clean Way" (XML).

The "Dirty" Way: Unsafe OkHttpClient

The "Dirty" Way: Unsafe OkHttpClient

You can create a custom OkHttpClient that trusts all certificates. This is useful for quick debugging but risky if not handled correctly. (See the OkHttp GitHub for more).

UnsafeOkHttpClient.kt
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
import okhttp3.OkHttpClient

fun getUnsafeOkHttpClient(): OkHttpClient {
    // 🚨 SAFETY CHECK: Only allow in Debug builds
    if (!BuildConfig.DEBUG) {
        throw RuntimeException("Unsafe client not allowed in production!")
    }

    val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
        override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
        override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
        override fun getAcceptedIssuers() = arrayOf<X509Certificate>()
    })

    val sslContext = SSLContext.getInstance("SSL")
    sslContext.init(null, trustAllCerts, java.security.SecureRandom())

    return OkHttpClient.Builder()
        .sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
        .hostnameVerifier { _, _ -> true } // 🚨 Trust all hostnames
        .build()
}

// Usage with Retrofit
val retrofit = Retrofit.Builder()
    .baseUrl("https://api.dev.com")
    .client(getUnsafeOkHttpClient()) // <--- Inject here
    .addConverterFactory(GsonConverterFactory.create())
    .build()
Show Java Version (Legacy)
UnsafeOkHttpClient.java
public static OkHttpClient getUnsafeOkHttpClient() {
    try {
        final TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            }
        };

        final SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
        builder.hostnameVerifier((hostname, session) -> true);

        return builder.build();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

The "Clean" Way: Network Security Config

Instead of modifying your code, you can tell Android to trust user-installed certificates only in debug builds. This is the official and recommended way (see Android Docs).

Note: This is required for Android 9 (API 28) and above, where cleartext traffic and user certificates are blocked by default.

Important: This method works for the standard network stack. If you create a custom SSLContext manually in code (like in the 'Dirty Way' above), Android ignores this XML file.

1. Create res/xml/network_security_config.xml

res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <debug-overrides>
        <trust-anchors>
            <!-- Trust user added CAs -->
            <certificates src="user" />
            <certificates src="system" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

2. Apply in AndroidManifest.xml

Reference the file exactly as @xml/network_security_config.

AndroidManifest.xml
<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >
    ...
</application>
Want to setup the Proxy properly? Check out our guide on how to configure the Android Emulator.

3. Verification

To verify, inspect traffic in Debuggo or Charles Proxy. If you see HTTPS content (JSON) instead of "Unknown", the bypass is working correctly.

Start Chaos Testing on Android

Get Free Proxy Account

Stop bypassing SSL manually.

Get Cloud Proxy