§ Example report
com.android.insecurebankv2
v1.0
This is a deliberately-vulnerable demo app. Run the same 89 analyzers on your release APK — your first scan is free.
Scan your app — free, no cardSeverity breakdown
9 high 29 med 10 low 0 info
Critical 0
High 9
Medium 29
Low 10
Info 0
False positives 0
Scan metadata
Package
com.android.insecurebankv2
Version
1.0
Size
3.3 MB
SHA-256
b18af2a0e44d7634bbcdf93664d9c78a2695e050393fcfbb5e8b91f902d194a4
Findings
137
Started
Nov 6, 2026
9:15:16 PM
Finished
Nov 6, 2026
9:15:42 PM
Duration
26s
Sandbox image
atomic-scanner-sandbox:2026-11-06-3945858694
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. The message leaves the device over the mobile network and may be charged to the user. On Android 4.4 (API 19) and later the system also writes text messages sent by an app that is not the default SMS app to the SMS provider, so the send is normally visible in the user's messaging app, but only after the data has left the device.
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. The app targets API 22, so the flags still take effect on every Android version.
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
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` and `targetSdkVersion=22`, both below 24, and references no `android:networkSecurityConfig`. Without an explicit config an app that targets API 23 or lower trusts **user-installed CAs** on every Android version: on Android 7.0 (API 24) and later its default config keeps them, and older releases have no other policy. A CA that the user, or a corporate or MITM device-admin profile, installs can therefore intercept the app's TLS traffic.
M8 MASVS-PLATFORM
platform.tapjacking
4 instances — click to expand
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.analytics.Tracker crypto.insecure_random
- java.lang.Math.random() called in com.google.android.gms.tagmanager.zzaj 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.ads.internal.client.zzl crypto.insecure_random
- java.lang.Math.random() called in com.google.android.gms.tagmanager.zzcc crypto.insecure_random
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.DoTransfer.RequestDoGets2 network.cleartext_urls
- Cleartext (http://) URL literals in DEX strings (3) network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.DoTransfer.RequestDoTransferTask network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.DoLogin.RequestTask network.cleartext_urls
- Deprecated `DefaultHttpClient` used in com.android.insecurebankv2.ChangePassword.RequestChangePasswordTask network.cleartext_urls
- WebView.setJavaScriptEnabled(true) in com.google.android.gms.internal.zzfd platform.webview
- WebView.setJavaScriptEnabled(true) in com.google.android.gms.internal.zzig platform.webview
- WebView.setJavaScriptEnabled(true) in com.android.insecurebankv2.ViewStatement platform.webview
- 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
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.os.EnvironmentCompat storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in android.support.v4.content.FileProvider storage.external_storage_apis
- External-storage API used: Environment.getExternalStorageDirectory in com.google.android.gms.internal.zzcb storage.external_storage_apis
- App-scoped external-storage API used: Context.getExternalCacheDir in android.support.v4.content.ContextCompatFroyo 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 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.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 (2 calls) in void com.android.insecurebankv2.ViewStatement.onCreate(Bundle) storage.external_storage_apis
- External-storage state query: Environment.getExternalStorageState in android.support.v4.os.EnvironmentCompat storage.external_storage_apis