The Android CA Trust Store Across Versions
⚠️ Authorization. This is reference material for the Android Pentest series. Everything here targets devices you own or are explicitly authorized to test.
Before you touch a single adb command, you need to know which trust
model your target device uses. Picking the wrong injection method wastes
hours because Android silently ignores a CA it doesn’t trust — no error,
HTTPS just keeps failing. There isn’t one Android-14 fork; there are
three historical breakpoints, and each changes whether you need root and
how you install the certificate.
The four eras of the CA trust store
adb shell getprop ro.build.version.release
Android ≤ 6 (API ≤ 23) ──► apps trust USER store by default
→ install via Settings, NO ROOT NEEDED
Android 7–8 (API 24–27)──► apps trust SYSTEM store only by default
→ must write /system/etc/security/cacerts/
→ ROOT REQUIRED
Android 9–13 (API 28–33)──► same as above, but system-as-root /
read-only root makes the remount fail
→ ROOT + tmpfs overlay fallback
Android 14+ (API 34+) ──► trust store moved into an APEX module with
per-process mount namespaces
→ ROOT + APEX namespace injection
Android ≤ 6 — the easy era (no root)
Apps trusted user-installed CAs by default. You could push the BurpSuite CA through Settings → Security → Install from storage and intercept traffic on a stock, unrooted device. This is why old tutorials say “just install the cert” — that advice is wrong for anything modern.
Android 7+ — the breakpoint that defines this series
Android 7 (Nougat, API 24)
changed the default network_security_config: apps no longer trust the
user store unless the developer explicitly opts in. From here on, a CA in
the user store is invisible to most apps. Your only reliable option is the
system store at /system/etc/security/cacerts/ — which requires root.
📌 This is why the whole series assumes a rooted device. It is not a convenience; from Android 7 onward there is no unrooted path that works against a typical hardened app.
The one exception: if the app ships a network_security_config.xml with
<certificates src="user" />, the old user-store trick still works. Worth
checking — decompile the APK and look at res/xml/.
Android 9–10 — the remount stops working
Functionally the same trust model as Android 7–8, but Google introduced
system-as-root and increasingly read-only /system. The classic
mount -o rw,remount /system now frequently fails with “Read-only file
system”. The workaround is a tmpfs overlay on the cacerts directory —
see install_cert.sh. Note this overlay is
memory-only and does not survive a reboot.
Android 14+ — APEX namespaces
The CA store moved under an APEX module with per-process mount namespaces forked from Zygote. A single file copy is no longer enough — the cert has to be injected into every running namespace. This is the deepest change and is covered separately.
Decision flow
┌─────────────────────────────┐
│ getprop version + check APK │
│ network_security_config.xml │
└──────────────┬───────────────┘
│
┌──────────────────────┼───────────────────────┐
▼ ▼ ▼
Android ≤ 6 Android 7–13 Android 14+
OR app opts into (system store only) (APEX namespaces)
user CA │ │
│ ▼ ▼
▼ remount works? ──no──► tmpfs overlay
Settings install │ yes │
(no root) ▼ ▼
direct /system push APEX namespace injection
(Part: pre-14) (Part: 14+)
Quick reference table
| Android | API | Default trust | Root? | Install method |
|---|---|---|---|---|
| ≤ 6 | ≤ 23 | User + System | No | Settings → Install from storage |
| 7–8 | 24–27 | System only | Yes | Push to /system/etc/security/cacerts/ |
| 9–13 | 28–33 | System only | Yes | Same, often needs tmpfs overlay |
| 14+ | 34+ | System (APEX) | Yes | APEX per-namespace injection |
See also
- Previous: Overview
- Next: ADB & Frida Setup
- Certificate Injection — Android < 14 — the
7–13path in practice - Certificate Injection — Android 14+ (APEX) — the
14+path