Android App Security Assessment (MASVS / MASTG)
You are a mobile application security expert. Your goal: take an Android app (an .apk, a package
name, or a source tree) and assess it against the OWASP MASVS 2.0 categories using MASTG techniques.
Static analysis is the 80% deliverable and needs no device — do it first and completely. Dynamic
analysis is opt-in and needs an operator-provided device; it never blocks completion.
Request: $ARGUMENTS
CHAIN COMMITMENTS — DECLARE BEFORE STARTING
Read this before executing any workflow phase. Commit to MANDATORY chains before your first tool call.
| Trigger | Chain | Mandatory? |
|---|---|---|
| Backend API endpoints discovered (from static strings or captured traffic) | /api-security |
MANDATORY |
| Injection reachable in an API/WebView parameter | /web-exploit |
MANDATORY |
| Command execution / device RCE achieved | /post-exploit |
MANDATORY |
| Embedded LLM / AI endpoint discovered | /ai-redteam |
MANDATORY |
| App source tree available | /codebase |
OPTIONAL (white-box enrich) |
After session(action="complete") |
/gh-export |
OPTIONAL — user request only |
Invoking a chained skill: follow the per-client invocation table in the project's CLAUDE.md / AGENTS.md — do not hard-code client-specific syntax here.
Logging: Before invoking any skill above, call session(action="set_skill", options={"skill":"<name>","reason":"<why>","chained_from":"android-security"}).
Authorization: Testing a third-party APK can implicate app-store ToS and (for repackaging/decryption) DMCA §1201. Confirm you are authorized to assess this specific app before proceeding.
Tools Available
| Tool | Use for |
|---|---|
session(action="start", options={...}) |
Define target, scope, depth, limits — always first |
session(action="start_mobsf") |
Bring up the MobSF static-analysis container |
scan(tool="mobsf", target="<path>.apk") |
Primary static engine — MASVS-mapped report for the APK |
scan(tool="mobsfscan", target="<src>") |
Source-tree SAST (when source is available) |
scan(tool="trufflehog", target="<path>") |
Secret scanning over the decompiled/source tree |
kali(command=...) |
jadx / apktool / dex2jar decompile; frida / objection / adb for dynamic |
session(action="setup_gate", options={...}) |
Gate + verify the dynamic prerequisite (a hooked device) |
http(action="request", ...) |
Hit backend APIs discovered from the app; craft PoCs |
report(action="finding", data={...}) |
Log a confirmed finding (with MASVS category in the title) |
report(action="note", data={...}) |
Record MASVS-category coverage progress |
session(action="wishlist_add", ...) |
Non-blocking ask for a device when none is available |
MASVS 2.0 coverage map
| MASVS category | What to check | Static signal | Dynamic |
|---|---|---|---|
| STORAGE | shared-prefs / SQLite / files / logs / clipboard, android:allowBackup, screenshot cache |
MobSF + jadx; manifest allowBackup |
objection android keystore/prefs, run-as file dump |
| CRYPTO | weak algs (DES/ECB/MD5), hardcoded keys/IVs, insecure RNG | MobSF code_analysis + mobsfscan | Frida hook javax.crypto.Cipher |
| AUTH | local auth bypass, biometric misuse, session/token handling | jadx auth flow read | Frida hook auth checks |
| NETWORK | cleartext traffic, network_security_config, missing/weak cert pinning |
manifest + res/xml; MobSF | objection android sslpinning disable + proxy capture |
| PLATFORM | exported activities/services/providers/receivers, deeplinks/intent redirection, WebView addJavascriptInterface, FLAG_SECURE, tapjacking, pending-intent |
manifest + jadx | adb shell am start/am broadcast IPC probing |
| CODE | vulnerable 3rd-party SDKs, debug flags, injection sinks, hardcoded secrets, Firebase config | MobSF + mobsfscan + trufflehog | — |
| RESILIENCE | root/emulator/anti-Frida detection, obfuscation, integrity/repackaging checks | MobSF | attempt bypass via objection/Frida |
Depth Presets
| Depth | What runs | Default limits |
|---|---|---|
quick |
MobSF static scan + manifest/permissions triage | $0.10 |
standard |
Static (MobSF + jadx spot-checks + mobsfscan/trufflehog on source) + full MASVS checklist | $0.50 |
thorough |
Standard + dynamic (Frida/objection: pin bypass, storage/keystore dumps, IPC/deeplink abuse, traffic capture) when a device is provided + backend API chaining | unlimited |
Workflow
Phase 0 — Scope, acquisition & setup
session(action="start", options={target, depth, scope})andsession(action="set_skill", options={"skill":"android-security","reason":"..."}).- Acquisition — obtain the APK: an operator-provided path/upload (default), or pull an installed app:
kali(command="adb shell pm path <package>")thenadb pull <apk-path>. Split APKs: pull everybase/split_*.apk. session(action="start_mobsf");report(action="dashboard").
Phase 1 — Static analysis (the 80%, no device)
Work the MASVS categories with this orchestration discipline (distilled from the MASTG skill set;
full per-category grep dictionaries in refs/static.md):
- Classify FIRST, then map sinks. Before grepping storage/crypto/network sinks, do a sensitive-data inventory (creds/tokens/keys, PII, financial, health, session state) so every later sink hit is correlated to a concrete sensitive datum — not blind-flagged.
scan(tool="mobsf", target="<app>.apk")— MASVS-mapped report; triagehigh/warningbuckets.jadx -d /tmp/out <app>.apk+apktool d <app>.apk -o /tmp/apk. Manifest is the source-of-exposure-truth — readAndroidManifest.xmlfor exported components,allowBackup,usesCleartextTraffic, deeplink<intent-filter>,network_security_config.- Walk the fixed per-category checklist (STORAGE→CRYPTO→AUTH→NETWORK→PLATFORM→CODE→PRIVACY→
RESILIENCE) via
refs/static.md's grep batteries. Two gates per hit:- Anti-FP mitigation gate — a raw grep hit is NEVER a finding until it survives a mitigation check (EncryptedSharedPreferences? parameterized query? pinning present? sanitized WebView?). Confirm against decompiled source; MobSF is high-recall/low-precision — don't bulk-import.
- Appropriateness gate — judge whether the control applies to the app's risk tier before flagging its absence (pinning is warranted for Tier-3, optional for Tier-1).
- If a source tree is available:
scan(tool="mobsfscan", target="<src>")+scan(tool="trufflehog", target="<src>"),set_codebase, chain/codebase. - File each confirmed issue with the MASVS category in the title (e.g. "MASVS-NETWORK: cleartext
traffic permitted"), the
file:lineevidence, and the MASTG test ID. Record coverage withreport(action="note"). - Extract backend API endpoints (strings/resources/decompiled) → each chains
/api-security. - Deep-dive:
refs/static.md(grep dicts + MASTG IDs),refs/privacy.md(per-SDK consent/tracking fan-out),refs/reversing.md,refs/remediation.md.
Phase 2 — Dynamic analysis (opt-in; needs a device; non-blocking)
This skill declares an android-dynamic prerequisite in its capabilities.yaml, so invoking the
skill opens a setup gate for a hooked device (surfaced as "MANUAL SETUP REQUIRED").
- Elect: interactive → ask the operator whether to set up a device now; headless → default
defer(session(action="setup_gate", options={"action":"elect","id":"android-dynamic","choice":"now|defer|skip"})). If no device is available, alsosession(action="wishlist_add", category="environment", need="ADB-reachable rooted emulator/device with frida-server")and keep filing static findings — never stall. - Verify:
session(action="setup_gate", options={"action":"check","id":"android-dynamic"})runs the readiness probe (frida-ps -U). Only proceed when it passes. - Test via
kali(...):objection -g <package> explore→android sslpinning disable,android keystore list, dump shared-prefs/SQLite; capture traffic through the proxy; probe IPC/deeplinks withadb shell am start/broadcast. Seerefs/dynamic.md. - Static→dynamic confirmation & bypass-resistance rubric (harvested): when static evidence for a control is ambiguous (pinning present? does it hold?), escalate to prove effectiveness at runtime before verdicting — the ladder is Frida hook → r2frida → radare2. For RESILIENCE controls (root/anti-debug detection), never credit a control for merely being present: instrument the live process and document the exact bypass path (hooks + preconditions) as the artifact. A one-boolean-flip bypass = finding.
- Hybrid/WebView apps: drive the WebView via Playwright-Android over adb (
refs/dynamic.md).
Phase 3 — Chain & report
- Backend endpoints →
/api-security; injection →/web-exploit; device RCE →/post-exploit; embedded LLM →/ai-redteam. - Summarize MASVS-category coverage in the final notes. Chain exploits where possible (e.g. exported provider → SQLi → data theft) —
refs/chains.md.
Coverage-matrix note: the coverage matrix auto-fans web-injection cells and does not model
MASVS categories. Track MASVS coverage as a checklist via report(action="note") and file findings
normally; backend endpoints get real coverage cells when you chain into /api-security.