# Android apps don't trust user-installed CAs: why and fixes

> Since Android 7, apps ignore CA certificates installed by the user. Why company or debugging CAs work in Chrome but not apps, and how to configure trust.

Source: https://ssl.sh/errors/android-app-user-ca-not-trusted/
Last updated: 2026-11-10

**On Android 7.0 and later, apps ignore CA certificates that the user installed unless the app explicitly opts in.** That is why a company root, a school Wi-Fi certificate or a debugging proxy root makes websites work in Chrome while apps keep failing with certificate errors. This is intentional platform security, not a bug on the phone.

## Is it the site or your device?

The device works as designed; the fix belongs in the app or on the server. Check whether the server needs a private CA at all with the [SSL checker](https://ssl.sh/tools/ssl-checker/):

```bash
curl ssl.sh/example.com
```

- **The server has a valid public certificate:** apps should work without any user CA. If they fail only on a certain network, that network is intercepting TLS (see [corporate SSL inspection](https://ssl.sh/errors/corporate-ssl-inspection/)).
- **The server uses a private CA or the traffic must pass an inspection proxy:** the app must be configured to trust that CA, or the server must switch to a public certificate.

## Causes

### 1. App targets API 24+ and does not opt in to user CAs

The default trust configuration for modern apps contains only system CAs. Installing a root under Settings changes nothing for these apps. Developers confirm it with:

```bash
adb logcat | grep -iE "trust anchor|CertPathValidatorException|SSLHandshakeException"
```

### 2. Corporate network with SSL inspection

The company proxy re-signs HTTPS with its own root. Browsers that honour user or admin CAs work; apps fail. The fix is on the corporate side: exclude app traffic from inspection or manage the device so apps receive the CA.

### 3. Debugging proxy root

Developers capturing app traffic install a proxy root as a user CA. Their own debug build needs `<debug-overrides>`; third-party release apps will not trust it, by design.

### 4. Private CA for internal APIs

Internal services signed by a company CA require the app to bundle that CA or reference it in the network security config.

## What it looks like on each device

| Context | What you see |
|---|---|
| Android apps (Java/Kotlin) | `javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.` |
| Chrome on Android | Works if the user CA is installed |
| Android system | Notification or label that the network may be monitored |
| iOS apps | Need the root installed and full trust enabled (see [iOS server identity](https://ssl.sh/errors/ios-cannot-verify-server-identity/)) |

## How site owners fix it

A public certificate on the server removes the need for any user CA; a private CA needs explicit trust in the app.

**1. Prefer public certificates** for any API that phones talk to. Then no user CA is needed, and `curl ssl.sh/example.com` will confirm the chain.

**2. Bundle a private CA for specific domains** in `res/xml/network_security_config.xml`:

```xml
<network-security-config>
  <domain-config>
    <domain includeSubdomains="true">internal.example.com</domain>
    <trust-anchors>
      <certificates src="@raw/company_root"/>
      <certificates src="system"/>
    </trust-anchors>
  </domain-config>
  <debug-overrides>
    <trust-anchors>
      <certificates src="user"/>
    </trust-anchors>
  </debug-overrides>
</network-security-config>
```

Reference it from the manifest with `android:networkSecurityConfig="@xml/network_security_config"`.

**3. Keep user-CA trust out of release builds** unless the app is built for managed corporate devices.
