Mobile Android Whitebox Audit
When this skill applies
The user is reviewing a decompiled Android target. Signals to look for:
- The working directory or referenced target contains
jadx_out/,jadx_out2/,apktool_out/,AndroidManifest.xml,*.smali, or jadx's signaturedefpackage/*.javafiles (obfuscated default-package classes). - The user mentions an APK, xAPK, or an Android package name
(
com.example.*,com.acme.app, etc.). - A previous run produced findings under
<target>/.claude/findings.jsonwhosetypestarts withmobile-*.
Workflow: prefer /vuln-scout:mobile-audit
For Android targets, the regular /vuln-scout:scan only sees one of the two
decompilation trees (code OR resources). Use the unified driver instead:
/vuln-scout:mobile-audit <target-root>
The driver auto-discovers jadx_out/sources (or jadx/sources,
decompiled/sources, android-decompiled/sources, src/main/java) for code
findings and apktool_out (or apktool, res) for manifest + NSC findings,
runs the orchestrator on each, and merges the artifacts into a single
<target>/.claude/findings.json. Use the --profile deep flag when CodeQL /
Joern are installed (run python3 vuln-scout/scripts/doctor.py to confirm).
High-signal detector cheatsheet
VulnScout ships dedicated mobile detectors. Each produces normalized findings
with the standard schema (stable_key, kind, severity, type, etc.).
| Detector | Type slug | What it finds |
|---|---|---|
detect_webview_js_injection | mobile-webview-js-injection | A <script> block or var X = JS literal assembled from native StringBuilder/helper calls — the in-WebView card-tokenization shape. Dispatched via evaluateJavascript somewhere in the call graph. |
detect_webview_unsafe_config | mobile-webview-file-access, mobile-webview-js-interface | setJavaScriptEnabled(true) + setAllowFileAccess(true) / addJavascriptInterface(). |
detect_remote_controlled_url | mobile-remote-controlled-endpoint | URL fetched from a config key (getString("*_URL"...)) and dispatched via OkHttp/Retrofit/CoroutineCallFactory — the remote-config URL-injection shape. |
detect_network_security_config_gaps | mobile-nsc-no-pinning, mobile-nsc-narrow-pinning, mobile-nsc-cleartext | Missing or partial cert pinning, cleartext traffic permitted. |
detect_android_manifest_issues | mobile-exported-component-no-permission, mobile-debuggable-build | Exported activity/service/receiver with no permission guard; debuggable production build. |
detect_android_storage_backup_issues | mobile-allow-backup-true, mobile-exported-provider, mobile-deeplink-host-wildcard | allowBackup=true; exported ContentProviders without permission; wildcard deeplink hosts. |
detect_insecure_crypto | mobile-insecure-crypto, mobile-insecure-random | AES default mode (ECB) / DES / 3DES / RC4 / MD5 / SHA-1 / HmacMD5; Math.random() / new Random() used for tokens/IVs/keys. |
detect_sensitive_sharedprefs | mobile-shared-prefs-sensitive | Tokens / passwords / JWTs / PANs written to non-Encrypted SharedPreferences. |
detect_log_sensitive_data | mobile-log-sensitive | Log.X call interpolating a variable whose name maps to a sensitive identifier. |
detect_insecure_tls | mobile-insecure-tls | Empty checkServerTrusted / always-true HostnameVerifier. |
detect_mobile_intent_redirection | mobile-intent-redirection | Activity re-launches an externally provided Intent (StrandHogg shape). |
detect_pendingintent_mutable | mobile-pendingintent-mutable | PendingIntent.get* with FLAG_MUTABLE. |
detect_hardcoded_secrets_simple | secret-hardcoded, secret-private-key | AKIA / sk_live_ / ghp_ / xoxb / -----BEGIN PRIVATE KEY----- blocks. |
Triage shortcuts
When findings.json is heavy, sort by these priorities first:
mobile-webview-js-injection+mobile-remote-controlled-endpointin the same package — that's a complete chain (server-influenced data flows into JS that runs in a privileged WebView).mobile-insecure-tls+mobile-nsc-no-pinning— MITM precondition holds for the entire app.mobile-shared-prefs-sensitivein an auth/identity package.mobile-exported-component-no-permissionon receivers/services that pass intents into payment, auth, or deeplink handlers.
Calibration anchors
If a code change to detectors needs validation, run against a decompiled
target with both jadx_out/sources/ and apktool_out/ present. A healthy
mobile target with a payment-tokenization flow should produce roughly:
- Total findings: 7–30 (mix of high/medium, plus a handful of hotspots)
depending on profile and how much obfuscated SDK code lives under
defpackage/ - Must include at least:
mobile-remote-controlled-endpointon a*TokenizeCardApi-style class where a*_URLkey is read from config and dispatchedmobile-webview-js-injectionon a payment package class that splices native values into a<script>literalmobile-nsc-narrow-pinningatapktool_out/res/xml/network_security_config.xmlwhenever pinning is declared but the pin-set is narrower than the app's API surface
Path-exclusion conventions
vuln_class_detectors.py strips findings inside well-known third-party paths
to keep noise out of decompiled APKs:
- Single-segment, root-only:
kotlin,kotlinx,java,javax,androidx,okhttp3,retrofit2,okio,dagger,tslib,j$… - Multi-segment, anywhere:
com/google/android/*,com/google/firebase/*,com/squareup/*,com/bumptech/glide/*,com/lexisnexisrisk/*,io/reactivex/*,io/sentry/*,org/maplibre/*…
Default-package classes (defpackage/jh5.java style) cannot be excluded by
path — review their content if a finding lands there.