§ Example report
com.android.insecurebankv2
v1.0
This is a deliberately-vulnerable demo app. Run the same 88 analyzers on your release APK — your first scan is free.
Scan your app — free, no cardSeverity breakdown
9 high 33 med 6 low 0 info
Critical 0
High 9
Medium 33
Low 6
Info 0
False positives 0
Scan metadata
Package
com.android.insecurebankv2
Version
1.0
Size
3.3 MB
SHA-256
b18af2a0e44d7634bbcdf93664d9c78a2695e050393fcfbb5e8b91f902d194a4
Findings
135
Started
Sep 20, 2026
2:45:58 AM
Finished
Sep 20, 2026
2:47:04 AM
Duration
1m 7s
Sandbox image
atomic-scanner-sandbox:dev
OWASP Mobile Top 10 (2024) — coverage
Click a category to filter the findings list.
Vulnerabilities 48
Sev Title OWASP / MASVS Plugin Description
M4 MASVS-CODE
code.sql_injection
3 instances — click to expand
high
APK signed with v1 scheme only
M7 MASVS-RESILIENCE
resilience.apk_signing
The APK is signed with the v1 (JAR) scheme only — no v2 or v3 signature. v1-only signatures are vulnerable to Janus (CVE-2017-13156) on Android < 24: an attacker can prepend a malicious DEX without invalidating the signature, allowing arbitrary code injection into the legitimate APK. Pre-Nougat devices represent a small but non-zero install base.
high
Application is debuggable
M7 MASVS-CODE
manifest.security_attributes
`android:debuggable="true"` is set on `<application>`. Debug builds expose JDWP, allow attaching a debugger to any process, and bypass platform tamper-detection paths — a release APK in this state is trivially modifiable on any unrooted device.
high
Data exfiltrated via SMS to an attacker-controlled number in com.android.insecurebankv2.MyBroadCastReceiver
M6 MASVS-PRIVACY
platform.sms_leak
`void com.android.insecurebankv2.MyBroadCastReceiver.onReceive(Context, Intent)` passes an attacker-controlled value as the SMS destination address to `SmsManager.sendTextMessage`. The taint analyzer traces it back to an incoming `Intent` extra. Whoever sends that Intent (a hostile app broadcasting to an exported receiver, a malicious caller of an exported component) chooses the recipient, turning the send into a data-exfiltration primitive: the app SMSes device data to a number the attacker picks. The message body carries data the analyzer traces to a stored secret / credential source, so an actual credential is being exfiltrated — not just an empty relay. SMS leaves the device entirely — there is no on-device audit trail and the carrier bills the send.
high
getSharedPreferences called with MODE_WORLD_READABLE in com.android.insecurebankv2.MyBroadCastReceiver
M9 MASVS-STORAGE
storage.world_accessible_modes
`void com.android.insecurebankv2.MyBroadCastReceiver.onReceive(Context, Intent)` calls `getSharedPreferences` with `MODE_WORLD_READABLE` set on the mode argument. Files / databases / shared-prefs created with these flags are readable (and/or writeable) by every other app on the device — credentials, tokens, anything stored there leaks. Both flags have been deprecated since API 17 and rejected outright since API 24.
high
Hardcoded credential comparison in com.android.insecurebankv2.DoLogin.RequestTask.postData()
M1 MASVS-AUTH
auth.hardcoded_credentials
`com.android.insecurebankv2.DoLogin.RequestTask.postData()` compares a runtime value against the hardcoded string literal `devadmin` via `String.equals(...)`. The literal is a well-known backdoor / privileged-role account name, so this is a hardcoded / backdoor credential check baked into the client: the account name (and any password compared the same way) ships in every copy of the APK and is recovered with a one-command `unzip` + `baksmali`. A credential compiled into client bytecode is shared by every install and cannot be rotated without shipping a new build — the classic hardcoded-credential (“backdoor login”) weakness, CWE-798.
high
WebView loads a file:// URL from external storage with JavaScript enabled in com.android.insecurebankv2.ViewStatement
M8 MASVS-PLATFORM
platform.webview
`void com.android.insecurebankv2.ViewStatement.onCreate(Bundle)` loads a `file://` URL into a WebView while JavaScript is enabled, and the URL is rooted in EXTERNAL storage (`Environment.getExternalStorageDirectory()` / `Context.getExternalFilesDir()`). External storage is world-readable on older Android and shared across apps, so any app — or a user with a file manager — can drop a crafted HTML/JS file at the loaded path. Because JavaScript runs, that attacker-controlled content executes inside the WebView: stored XSS, exfiltration of local files reachable through the `file://` origin, and abuse of any `addJavascriptInterface` bridge. All three signals co-occur in this method — a `file://` const-string, an external-storage directory lookup, and `setJavaScriptEnabled(true)`.
M9 MASVS-STORAGE
storage.logging_pii
6 instances — click to expand
M5 MASVS-NETWORK
network.cleartext_urls
4 instances — click to expand
M8 MASVS-PLATFORM
manifest.security_attributes
4 instances — click to expand
M9 MASVS-PLATFORM
platform.flag_secure
4 instances — click to expand
M8 MASVS-PLATFORM
platform.tapjacking
4 instances — click to expand
M10 MASVS-CRYPTO
crypto.hardcoded_keys
2 instances — click to expand
M10 MASVS-CRYPTO
crypto.static_iv
2 instances — click to expand
medium
Exported provider without permission: com.android.insecurebankv2.TrackUserContentProvider
M8 MASVS-PLATFORM
manifest.security_attributes
The provider `com.android.insecurebankv2.TrackUserContentProvider` is exported (or implicitly exported via its intent-filter) and declares no `android:permission` to gate access. Any other app on the device can launch / bind to / call into it without consent.
medium
Exported receiver without permission: com.android.insecurebankv2.MyBroadCastReceiver
M8 MASVS-PLATFORM
manifest.security_attributes
The receiver `com.android.insecurebankv2.MyBroadCastReceiver` is exported (or implicitly exported via its intent-filter) and declares no `android:permission` to gate access. Any other app on the device can launch / bind to / call into it without consent.
medium
OS command execution via Runtime.exec in com.android.insecurebankv2.PostLogin
M4 MASVS-CODE
code.native_bridge
`com.android.insecurebankv2.PostLogin.doesSUexist` spawns an operating-system process by calling `Runtime.exec` (`Runtime.exec` / `ProcessBuilder.start`). If any part of the command line is derived from untrusted input (an intent extra, a file, a network response, or user text) without strict validation, this is OS command injection (CWE-78): an attacker can run arbitrary shell commands with the app's permissions. Even a fixed command is a capability worth review — confirm where the command string comes from and whether the invoked binary is trusted.
medium
Outdated targetSdkVersion (22)
M8 MASVS-CODE
code.sdk_versions
`targetSdkVersion=22` is more than two Android releases behind the current API level (35). The app opts out of platform-side hardening shipped in newer releases (scoped storage, runtime broadcast restrictions, permission auto-revoke, mutable PendingIntent default flip, …) and is likely to be rejected by Google Play under their rolling target-API requirement.
medium
Sensitive data flows into ContentValues.put in com.android.insecurebankv2.DoLogin.RequestTask.1
M9 MASVS-STORAGE
storage.insecure_storage
`void com.android.insecurebankv2.DoLogin.RequestTask.1.run()` feeds `ContentValues.put` data the taint analyzer traces back to a credential / identifier / location source. Writing credential or PII material to SharedPreferences, a DataStore, or a SQLite database in plaintext leaves it readable to anyone who can reach the app's private storage — a backup extraction, a rooted device, an `adb backup`-eligible app, or a debuggable build. The same code path catches token / cookie / device-id / geolocation values flowing through this method.
medium
Untrusted Intent/Uri input reaches a filesystem path (new File()) in com.android.insecurebankv2.ViewStatement
M4 MASVS-PLATFORM
platform.path_traversal
`void com.android.insecurebankv2.ViewStatement.onCreate(Bundle)` builds a filesystem path via `java.io.File(File, String)` from data the taint analyzer traces back to incoming IPC input (`Intent.get*Extra` / `getData` / a `Uri` path part / `Bundle.getString`). The sender controls that string: a value like `../shared_prefs/prefs.xml` escapes the intended directory (path traversal, CWE-22), and even without `..` it can name a private file the feature never meant to expose — the MASTG-DEMO-0122 pattern, where an extra picks the file a `FileProvider` then shares. `com.android.insecurebankv2.ViewStatement` is an exported activity, so any app on the device can send it this input.
This is an intra-procedural taint result flagged for review — confirm the resolved path is not canonicalised and checked against the intended base directory before it is used.
medium
User-installed CAs implicitly trusted (minSdk 15, no NSC)
M5 MASVS-NETWORK
network.nsc
The app declares `minSdkVersion=15` (< 24) and references no `android:networkSecurityConfig`. On Android releases before API 24 the platform default trust store includes **user-installed CAs**, so without an explicit config the app trusts any CA the user — or a corporate/MITM device-admin box — has installed. Such an attacker can transparently intercept the app's TLS traffic. From API 24 the default switched to system-only trust anchors, so this exposure applies specifically to the pre-24 install base. (This is the `minSdk < 24` counterpart of `manifest.no_network_security_config`, which covers the `targetSdk >= 24` no-NSC case — the two are disjoint.)
low
Auto-backup is enabled
M9 MASVS-STORAGE
manifest.security_attributes
`android:allowBackup="true"` lets `adb backup` extract the app's private data on a debug-bridged device, and (on Android <12) lets Auto Backup ship the same data to the user's Google Drive — tokens and credentials in `shared_prefs/` / `databases/` ride along. `android:fullBackupContent and dataExtractionRules` are not declared, so that backup path is unscoped and captures everything by default.
low
Declared but unused permission: READ_CONTACTS
M6 MASVS-PRIVACY
privacy.unused_permissions
The manifest declares `android.permission.READ_CONTACTS` but no DEX class references the Android API this permission guards. Either the permission is dead weight left over from a removed feature, or the functionality that needs it lives in a native library / dynamic feature module the static analyser can't follow. Either way, the user-visible permission prompt is broader than the app actually requires.
low
Declared but unused permission: READ_CALL_LOG
M6 MASVS-PRIVACY
privacy.unused_permissions
The manifest declares `android.permission.READ_CALL_LOG` but no DEX class references the Android API this permission guards. Either the permission is dead weight left over from a removed feature, or the functionality that needs it lives in a native library / dynamic feature module the static analyser can't follow. Either way, the user-visible permission prompt is broader than the app actually requires.
low
No anti-debug / signature-check signal found
M7 MASVS-RESILIENCE
resilience.tamper_detection
No reference to `Debug.isDebuggerConnected`, `PackageManager.checkSignatures`, or other classic tamper-detection APIs. For apps handling sensitive data MASVS-RESILIENCE expects at least one active-debugger check + a signature self-check.
low
No obfuscation detected (33 app classes inspected, 0% short-named)
M7 MASVS-RESILIENCE
resilience.obfuscation_estimate
Of 33 app-owned classes (excluding framework / AndroidX / Kotlin / Google Play / OkHttp / Retrofit / RxJava / similar curated-out packages), only 0% carry single-character simple names — the share R8 / ProGuard typically produces. Class, method, and field names are intact, which gives a reverse engineer a free map of your business logic and accelerates RE of any custom anti-tamper / crypto / licensing code shipped with the app.
low
No shouldShowRequestPermissionRationale calls (8 runtime permissions declared)
M6 MASVS-PRIVACY
privacy.permission_rationale
The app declares one or more runtime-grantable permissions but no class calls `Activity.shouldShowRequestPermissionRationale` or `ActivityCompat.shouldShowRequestPermissionRationale`. Users denied a permission once will be re-prompted without any context for why the app needs access — typically leading to permanent denial without informed consent, which Google's Permissions Best Practices and MASVS-PRIVACY-2 both call out as a privacy / UX smell.
Findings 2
Findings that need human review — the scanner can't confirm exploitability on its own. Severity varies: some are low-signal, others are real weaknesses worth confirming.
Sev Title OWASP / MASVS Plugin Description
M4 MASVS-CODE
code.sql_injection
2 instances — click to expand
Security posture
1 present · 6 absent · 0 partialTransport
Screen capture
Anti-tampering
Build
App inventory
What the app is — declared permissions, bundled SDKs, signing, build config. Reference, not findings.
| Permission | Risk | Status | Note |
|---|---|---|---|
| READ_CALL_LOG | medium | unused | declared but no gated API referenced — consider removing |
| READ_CONTACTS | medium | unused | declared but no gated API referenced — consider removing |
| READ_EXTERNAL_STORAGE | low | used | an API this permission gates is referenced in code |
| READ_PHONE_STATE | low | used | an API this permission gates is referenced in code |
| SEND_SMS | high | used | an API this permission gates is referenced in code |
| WRITE_EXTERNAL_STORAGE | low | used | an API this permission gates is referenced in code |
| ACCESS_COARSE_LOCATION | low | declared | not statically checkable for usage |
| GET_ACCOUNTS | low | declared | not statically checkable for usage |
| Component | Kind | Version | Category | PII |
|---|---|---|---|---|
| Google AdMob | sdk | — | advertising | ad_id, device_id, device_meta, network_meta |
| Google Tag Manager | sdk | — | analytics | device_meta, app_events |
| Google Play Services | library | — | — | — |
Signing
- Schemes
- v1
- Key
- —
- Subject
- —
- Validity
- —
- Issues
- APK signed with v1 scheme only
App profile
- minSdk/target
- 15 / 22
- Minification
- none (0.0)
- Network config
- absent
- Legacy storage
- —
- Native libs
- extracted: —
- StrictMode
- no
Other inventory (28)
- Framework: Native Android (confidence: low) code.framework_detection
- java.util.Random instantiated in com.google.android.gms.ads.internal.client.zzl crypto.insecure_random
- java.lang.Math.random() called in com.google.android.gms.tagmanager.zzaj crypto.insecure_random
- java.lang.Math.random() called in com.google.android.gms.tagmanager.zzcc crypto.insecure_random
- java.util.Random instantiated in com.google.android.gms.iid.zzc crypto.insecure_random
- java.util.Random instantiated in com.google.android.gms.analytics.Tracker crypto.insecure_random
- Cleartext (http://) URL literals in DEX strings (3) network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.DoLogin.RequestTask network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.DoTransfer.RequestDoGets2 network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.DoTransfer.RequestDoTransferTask network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.ChangePassword.RequestChangePasswordTask network.cleartext_urls
- WebView.setJavaScriptEnabled(true) in com.google.android.gms.internal.zzig platform.webview
- WebView.setJavaScriptEnabled(true) in com.android.insecurebankv2.ViewStatement platform.webview
- WebView.setJavaScriptEnabled(true) in com.google.android.gms.internal.zzfd platform.webview
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.content.FileProvider storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.os.EnvironmentCompat storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory (2 calls) in void com.android.insecurebankv2.DoTransfer.RequestDoTransferTask.1.run() storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory (2 calls) in void com.android.insecurebankv2.ViewStatement.onCreate(Bundle) storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in com.google.android.gms.internal.zzcb storage.external_storage_apis
- External-storage state query: Environment.getExternalStorageState in android.support.v4.os.EnvironmentCompat storage.external_storage_apis
- External-storage state query: Environment.getExternalStorageState in com.google.android.gms.internal.zzbq storage.external_storage_apis
- App-scoped external-storage API used: Context.getExternalFilesDir in android.support.v4.content.ContextCompatFroyo storage.external_storage_apis
- App-scoped external-storage API used: Context.getExternalCacheDir in android.support.v4.content.ContextCompatFroyo storage.external_storage_apis
- App-scoped external-storage API used: Context.getExternalFilesDirs in android.support.v4.content.ContextCompatKitKat storage.external_storage_apis
- App-scoped external-storage API used: Context.getExternalCacheDirs in android.support.v4.content.ContextCompatKitKat storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.content.ContextCompat storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.content.ContextCompat storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.content.ContextCompat storage.external_storage_apis