Android app testing rewards a method. The apps vary wildly, but the places bugs hide do not: an over-exported component, a secret baked into the APK, a token in plaintext storage, a business-logic check that only exists in the UI. Walk the same route every time and you stop missing the obvious and start finding the subtle.
This is the repeatable Android methodology I use, mapped to OWASP MASVS v2 (the Mobile Application Security Verification Standard — the community baseline for what a secure mobile app must do) and backed by the MASTG (the Mobile Application Security Testing Guide, which turns those requirements into concrete tests). It covers static review, dynamic instrumentation with Frida, the network and storage layers, mobile auth logic, and reporting. Everything here assumes you are testing an app you are authorized to test.
Scoping and setup
Before touching the app, pin down authorization and environment. Every technique below is legitimate only on apps you own or are explicitly contracted to test; a signed scope and rules of engagement come first. A practical lab:
- A test device or emulator you control. A rooted device or rootable emulator gives you the access instrumentation needs. Keep a non-rooted path in mind too, to see what an attacker without root can do.
- An intercepting proxy. Route traffic through it and install your CA. Expect certificate pinning and plan for it.
- The artifacts: the APK (or split APKs / AAB), and ideally a debug build and source for a white-box engagement.
The honest framing: rooting and pinning bypass are techniques for your lab, to observe an app you are allowed to inspect — not a way around someone else's protections in the wild.
Static review
Static review is cheap and finds a surprising share of real issues. Start with the manifest, which declares the app's attack surface.
The manifest
Unpack the APK and read AndroidManifest.xml. I look for:
- Exported components. An
activity,service,receiverorproviderwithandroid:exported="true"(or an implying intent filter) can be invoked by other apps. An exported activity that performs a privileged action without checking the caller is an IPC bug. - Deep links.
scheme/hostintent filters define URLs that launch the app. If a deep link feeds navigation, a WebView or a server call, it is attacker-reachable input. android:allowBackup. Iftrue, app data can be pulled via ADB backup on many configurations — a cheap route to local data.networkSecurityConfig. Read it: it tells you whether cleartext is allowed and how pinning and trust anchors are configured.
Secrets and the obfuscation misconception
Decompile and grep the smali/Java and resources for API keys, tokens, endpoints and credentials; they show up constantly in string resources, BuildConfig, and third-party SDK config.
The misconception I correct most often: obfuscation is not security. Obfuscation renames symbols; it does not remove a hardcoded key from the binary, and anyone with the APK can extract it. The correct control is to not ship the secret at all: keep it server-side behind an authenticated call. If a credential is in the APK, treat it as public.
This maps to MASVS-STORAGE (data should not be exposed) and MASVS-CRYPTO (keys handled properly).
Dynamic: the Frida workflow
Frida is a dynamic instrumentation toolkit: it injects a JavaScript engine into a running process so you can hook functions, read and change arguments and return values, and observe behaviour live — what the app actually does, not what the decompiled code suggests.
The workflow is always the same shape: attach, find the method, hook it, observe or modify.
// Generic shape of a Frida hook — observe a method's inputs and output.
Java.perform(function () {
var Target = Java.use("com.example.app.SomeClass");
Target.someMethod.implementation = function (arg) {
console.log("[*] someMethod called with: " + arg);
var result = this.someMethod(arg); // call the original
console.log("[*] someMethod returned: " + result);
return result; // pass it through unchanged
};
});
Two bypasses come up on almost every engagement, both legitimate in your own lab to let you observe the app:
- Root detection. Apps often refuse to run on rooted devices. For testing, you hook the detection so it reports "not rooted" and proceed to the actual review. The finding worth reporting is rarely "root detection can be bypassed" (it almost always can); it is whatever sensitive behaviour the detection was guarding.
- Certificate pinning. Pinning stops your proxy from reading TLS traffic. In the lab you hook the check so your own CA is accepted and you can inspect the API calls. The deliverable is what you find in that traffic, not that pinning was bypassable on a device you fully control.
Keep the distinction clear in your report: bypassing a control to observe the app is method; a control that fails to protect data an attacker can reach is a finding.
Network layer
With traffic visible, the network layer is where mobile meets API testing (MASVS-NETWORK and MASVS-AUTH territory).
- TLS configuration. Confirm cleartext is not allowed, the app validates certificates when you are not intervening, and
networkSecurityConfigmatches reality. - Token handling. Where does the auth token live, how is it sent, does it expire, what happens on logout? A token that never expires or is logged is a finding.
- The API itself. Mobile apps are often the most honest client of an API, exposing endpoints a web UI hides. Everything from object-level authorization to mass assignment applies — I test these exactly as I would any API (see BOLA and the API bugs that still pay for the matrix), because the mobile client is just another caller of the same backend.
Local storage and IPC
What the app leaves on the device, and how it talks to other apps, is where mobile findings cluster (MASVS-STORAGE and MASVS-PLATFORM).
- SharedPreferences and databases. Pull the app's data directory and read it. Tokens, PII or credentials in plaintext
SharedPreferencesXML or an unencrypted SQLite database is a classic, high-value finding. - Logs. Watch
logcatwhile you use the app. Apps leak tokens, OTPs and PII into logs more often than anyone expects. - Clipboard. Sensitive values copied to the clipboard are readable by other apps on older platforms; check whether the app copies secrets.
- Content providers. An exported or misconfigured
ContentProvidercan expose internal data to other apps. Query it and see what comes back. - Intents and IPC. Feed crafted intents to exported components. Does an exported activity trust extras it should not, or forward data into a privileged action?
- WebView settings.
setJavaScriptEnabled(true)withaddJavascriptInterfaceor untrusted content is a path to code reaching native bridges. Check what the WebView loads and exposes.
A worked example: an app stores the session token in plaintext SharedPreferences and allowBackup is true. Neither alone feels dramatic, but together the session is extractable via backup without root — storage weakness plus backup exposure equals account access. Chaining is what turns "medium" observations into accurate severity.
Business-logic and auth flows on mobile
Some of the best mobile findings are logic, not memory corruption.
- OTP and 2FA. Is the OTP verified server-side, or does the client decide? Can you brute-force it (no rate limit, no lockout)? Is it reusable? A client-side "correct OTP" check is a critical finding.
- Device binding and session. If the app claims to bind a session to a device, test whether a token lifted from one device works on another. Test logout, token refresh and concurrent sessions.
- Price/quantity and state. In fintech and commerce apps, check whether the client is trusted for values it should not be — amounts, limits, entitlements. The server must re-validate everything the client sends.
The through-line: the client is attacker-controlled. Any decision made only on the device can be changed with the instrumentation above, so every such decision must be re-made on the server.
Evidence and reporting
A finding is only as good as the proof. For each issue I capture:
- The exact request/response (from the proxy) or logcat line, with sensitive values redacted.
- A screenshot or short clip of the behaviour.
- Clear reproduction steps, including the device/OS and build tested.
- The MASVS category it violates and, where relevant, the CWE, so the developer can map it to a standard and a fix.
- An honest severity reflecting real impact and any chaining, not a number inflated to look impressive.
For running this repeatably I use SentryScan Mobile, my own tool for the Android workflow — static triage, instrumentation helpers and evidence capture in one place. It speeds the mechanical parts; the judgment calls are still yours.
Tester's checklist
- [ ] Confirm written authorization and scope before any instrumentation.
- [ ] Read the manifest: exported components, deep links,
allowBackup,networkSecurityConfig. - [ ] Grep for hardcoded secrets; treat anything in the APK as public.
- [ ] Attach Frida, bypass root/pinning in your lab, observe the real behaviour.
- [ ] Capture and review API traffic; apply the full API-authorization matrix.
- [ ] Inspect storage, logs, clipboard, content providers, intents and WebView.
- [ ] Test OTP, device binding and session logic for client-side trust.
- [ ] Record evidence with MASVS mapping and honest, chain-aware severity.
Fixes / defence
- Secrets: never ship them in the APK; keep them server-side behind authenticated calls. Obfuscation is not a control.
- Components: export only what must be exported; validate the caller and all intent input; set
allowBackup="false"for apps holding sensitive data. - Storage: encrypt sensitive data at rest, keep tokens out of plaintext
SharedPreferencesand logs, and clear secrets from the clipboard. - Network: enforce TLS, pin certificates (it raises the bar, it is not absolute), expire tokens and invalidate them on logout.
- Logic: re-validate every security decision server-side. Rate-limit and lock out OTP; never let the client verify an OTP or authorize a transaction.
- WebView: avoid untrusted content; constrain JavaScript bridges; disable what you do not use.
Takeaways
- Android testing is a route, not a grab bag. Walk static → dynamic → network → storage/IPC → logic every time and you stop missing the obvious.
- Map findings to MASVS v2 and verify with the MASTG; it gives you and the developer a shared, defensible language.
- Root and pinning bypass are method for your own lab. The deliverable is the data and logic behind them, not the bypass.
- The client is attacker-controlled; any check that lives only on the device can be flipped. Chain small weaknesses into accurate severity instead of reporting them in isolation.
Learn more
- OWASP MASVS v2 — Mobile Application Security Verification Standard (mas.owasp.org)
- OWASP MASTG — Mobile Application Security Testing Guide (mas.owasp.org)
- OWASP Mobile Top 10 (owasp.org)
- Android Developers — App security best practices and Network Security Configuration (developer.android.com)
- MITRE CWE-312: Cleartext Storage of Sensitive Information (cwe.mitre.org)
Related: BOLA, Mass Assignment and the API Bugs That Still Pay in 2026 · Bug Bounty in 2026: VDPs, AI-Assisted Triage and Hall of Fame Credit. Need this tested on your product? Book a free 30-minute scoping call.



