Mobile Certificate Pinning Bypass Notes for Authorized Testing
Pinning blocks your intercepting proxy. That is the point. On a program that allows mobile testing against accounts you own, you still need a clean way to see HTTPS bodies—without pretending every shipping app must be unpinable by strangers.
These notes are for lab devices, debug builds, and in-scope APKs/IPAs where the policy permits instrumentation.
Identify how pinning is implemented
Do not jump straight to a universal Frida script. Fingerprint the stack:
- OkHttp
CertificatePinnerin Android smali/Kotlin - Network Security Config with
<pin-set> - TrustKit, Cordova/Ionic plugins, or React Native libraries
- iOS
NSURLSessionserverTrust custom delegates, Alamofire evaluators, or embedded SPKI hashes
A static pin list in resources is different from SSL Kill Switch hopes on a locked-down production build. Root/jailbreak detection often sits next to pinning; treat them as a combined control. Flutter and React Native apps may pin inside a Dart/JS layer while the platform HTTP stack looks clean—search both.
Record leaf and intermediate pins if present. Backup pins that never rotate become a long-term liability for the vendor, but for you they are just another hash to document when explaining why a proxy CA was rejected.
Lab bypass patterns that stay scoped
Prefer the lightest change that yields traffic:
- Rebuild a debug variant the vendor gave you with pinning disabled.
- Patch the pin set in a sideloaded build you own and resign.
- Hook only the pin-check function on a jailbroken/rooted test device after confirming root detection will not brick the flow mid-session.
When you hook, log the host that failed validation and the expected hashes. Your report should show you understood the control, not that you pasted a public "unpin all" snippet and moved on.
Burp or mitmproxy with your CA installed remains necessary after the pin check is relaxed. Watch for secondary pins on WebViews, separate auth SDKs, and certificate transparency style checks that fail closed. Some apps pin only api. while cdn. or auth federated hosts stay ordinary TLS—map hosts before you assume one hook covers the session.
Android Network Security Config user CA trusts in debug manifests sometimes ship by mistake in release. If a release build trusts user-installed CAs without pinning, that is a shippable weakness on its own when policy treats insecure TLS as in scope. Spelling out build flavor evidence helps triage.
What belongs in the bounty report
Bypassing pinning on your device is rarely the vulnerability. The vulnerability is whatever sensitive IDOR, auth flaw, or logic bug you found once traffic was visible. Mention the pinning approach in Methodology so triage can reproduce.
Exceptions exist: hardcoded private keys, debug endpoints that disable TLS checks in production builds, or a pin that trusts a leftover test CA. Those are findings with APK/IPA evidence. A comment like // TODO remove TrustAllManager next to a custom X509TrustManager is not subtle—quote the class name and the package.
Keep payloads off shared devices. Do not distribute patched APKs of the target. If Frida scripts are needed for reproduction, describe the hooked symbol and wait for the program's preferred channel rather than attaching malware-looking binaries to a public HackerOne thread.
Recommend modern pinning with backup pins, remote configuration that does not brick users when pins rotate, and separate debug builds for security testers instead of leaving TRUST_ALL in release. OWASP's pinning control notes remain a fair baseline citation beside your proxy screenshots.