Skip to main content
Blog

Mobile

OWASP Mobile Top 10 (2024): M1 to M10 and what the security review checks in each

A walkthrough of the 2024 OWASP Mobile Top 10: what each category means, how the expert tests it, and how to prepare your app.

· 12 min read

Photo: Rawpixel Ltd, CC BY 2.0 · Wikimedia Commons

Open a mobile app security review report and you will often see two references next to each finding: a MASVS/MASWE identifier and an OWASP Mobile Top 10 category. For example, in the report on our own app, the finding "root detection not implemented" was tagged MASWE-0097 and M7 (Insufficient Binary Protections). The Mobile Top 10 is a list of the most important risk categories for mobile apps; it is maintained by the OWASP team, and the latest edition was published in 2024.

In this article we go through the list from M1 to M10: what each category means, what the review checks for it, how to check it yourself and how to fix it. Each section is short, with links to related articles for more detail.

How the list is used

The Mobile Top 10 is not a standard or a testing methodology; it is a map of risks. The hands-on testing is done against OWASP MASVS (requirements), MASTG (testing methods) and MASWE (weakness catalogue). The Top 10 groups findings into understandable categories and helps set priorities. That makes it a good starting checklist when preparing an app for the review.

M1: Improper Credential Usage

What it is: misuse of keys, passwords and tokens — API keys in code, a static token shared by all users, credentials stored or transmitted in plain form.

What the review checks: the APK/IPA is decompiled and strings are searched for keys, passwords and tokens; the credentials passed between app and server are observed.

Check it yourself:

jadx -d out app-release.apk
grep -rniE "api[_-]?key|secret|password|bearer" out/
strings -n 8 lib/arm64-v8a/libapp.so | grep -iE "key|secret"

Fix: secret keys live only on the server; the app calls the backend with the user's short-lived token. More: keys inside APK and IPA.

M2: Inadequate Supply Chain Security

What it is: risk coming through third-party libraries, SDKs and the build process: vulnerable or abandoned packages, untrusted sources, an unprotected CI and signing keys.

What the review checks: the libraries in the app and their versions, components with known vulnerabilities, unnecessary SDKs (for example, ad or analytics SDKs that request excessive permissions).

Check it yourself: in Flutter run flutter pub outdated, on Android ./gradlew app:dependencies, on iOS review Podfile.lock. For each dependency: who maintains it, when was it last updated, do we really need it.

Fix: lock files in the repository, dependencies updated regularly, unused SDKs removed, the release signing key kept in a safe place (Google Play App Signing or protected CI secrets).

M3: Insecure Authentication/Authorization

What it is: authentication and authorization mistakes — important decisions made only in the app, no permission checks on the server, weak session management, PIN or biometrics applied only at the UI level.

What the review checks: API requests are replayed with another user's identifier (IDOR), in-app checks are disabled with Frida, exported screens are opened without login, and token lifetime and post-logout state are tested.

Check it yourself: through a proxy, resend your own request with another user's ID; after logout, call the API with the old token.

Fix: permissions are checked on the server for every request, tokens are short-lived and revoked on the server at logout. More: IDOR and authorization errors, deep links and exported components.

M4: Insufficient Input/Output Validation

What it is: data from outside (user input, deep links, intents, server responses, QR codes) is used without validation. The result: XSS in a WebView, local SQL injection, path traversal, the wrong page opening inside the app.

What the review checks: deep link and intent parameters, URLs passed to WebViews, local SQLite queries, handling of file names.

Check it yourself:

adb shell am start -a android.intent.action.VIEW \
  -d "myapp://open?url=https://evil.example.com"

Fix: an allowlist for every external input, only parameterized queries in SQLite, restricted WebView navigation, and the same validation on the server. More: WebView security.

M5: Insecure Communication

What it is: insufficient protection of network communication — use of http, incorrect certificate validation, ignoring SSL errors, no pinning.

What the review checks: traffic is intercepted through a proxy; does the app accept the proxy certificate, are there http links, is there proceed() in onReceivedSslError. Our own app's report had two findings here: insecure certificate validation (high risk) and http links (low risk).

Check it yourself: install a Burp or mitmproxy certificate on the device and use the app. With correct pinning, the requests should fail.

Fix: on Android, network_security_config with cleartext disabled and a pin-set; in Flutter, a SecurityContext with only trusted root certificates; on iOS, no ATS exceptions:

<base-config cleartextTrafficPermitted="false" />

More: SSL pinning, allowBackup and cleartext.

M6: Inadequate Privacy Controls

What it is: personal data (name, phone number, personal ID number, location, documents) is collected beyond what is needed, written to logs, sent to third-party SDKs, or visible in screenshots and notifications.

What the review checks: requested permissions, personal data in logs (adb logcat), what is sent to analytics, what stays on screen when the app goes to the background.

Check it yourself:

adb logcat | grep -iE "token|phone|password|passport"

Fix: only necessary permissions and data, logs disabled in release, screenshots restricted on sensitive screens (FLAG_SECURE on Android), no personal data sent to analytics.

M7: Insufficient Binary Protections

What it is: the app binary is not protected against reverse engineering and modification: no obfuscation, no root/jailbreak or emulator detection, no resistance to dynamic analysis tools such as Frida, no integrity (tamper) check.

What the review checks: in our experience this is the category with the most findings. On Android, missing root detection, integrity checks and dynamic analysis protection were rated high risk, and missing emulator detection medium; on iOS, missing jailbreak detection and dynamic analysis protection were high risk.

Check it yourself: run the release build on a rooted device or an emulator, attach with frida-server, re-sign and install the APK. The app must detect each of these situations.

Fix: a RASP library (we used freeRASP) with a blocking screen, R8 minify and Dart obfuscation:

flutter build apk --release --obfuscate --split-debug-info=build/symbols

More: root and jailbreak detection, Frida and RASP, app integrity and obfuscation.

M8: Security Misconfiguration

What it is: mistakes in platform and app settings — debuggable=true, allowBackup=true, unnecessary exported components, excessive permissions, WebView debugging enabled in release, wrong file permissions.

What the review checks: the merged manifest, Info.plist, entitlements, build types.

Check it yourself:

apktool d app-release.apk -o app_src
grep -nE 'debuggable|allowBackup|exported="true"|usesCleartextTraffic' app_src/AndroidManifest.xml

Fix: no debuggable in release, allowBackup="false" plus dataExtractionRules, only necessary components exported, only necessary permissions requested.

M9: Insecure Data Storage

What it is: sensitive data stored on the device without protection — a token in SharedPreferences or NSUserDefaults, an unencrypted SQLite database, personal files in the cache, WebView cookies left after logout, data that ends up in backups.

What the review checks: the app's internal folder (/data/data/<package>/) is inspected on a rooted device. Our app had a high-risk finding here: "sensitive data stored unencrypted in internal storage".

Check it yourself:

adb shell run-as uz.example.app ls -R /data/data/uz.example.app/
adb shell run-as uz.example.app cat shared_prefs/FlutterSharedPreferences.xml

(run-as only works with a debug build; check the release build on a rooted test device.)

Fix: tokens and secrets in Keystore/Keychain (flutter_secure_storage in Flutter); all local data and WebView data cleared on logout. More: Keystore and Keychain.

M10: Insufficient Cryptography

What it is: cryptography used incorrectly — outdated algorithms (MD5 or SHA1 for passwords, DES, ECB mode), keys in code, a constant IV, a home-made "encryption algorithm", keys generated with Random.

What the review checks: in the decompiled code — Cipher.getInstance, MessageDigest, and where the key and IV come from.

Check it yourself:

grep -rnE 'AES/ECB|DES|MD5|SHA1|SecretKeySpec' out/sources

Fix: AES-GCM, keys generated and stored in Keystore/Keychain, a random IV every time, passwords hashed only on the server with bcrypt/Argon2. Best of all — do not write your own cryptography; rely on the platform and well-reviewed libraries.

One note: the review asks for MD5, SHA1 and SHA256 checksums of the submitted APK/IPA — that is not an M10 finding, just a way to identify the file. More: APK/IPA checksums.

Short pre-review checklist

  • M1: no secret keys and no shared static token in the app.
  • M2: dependencies updated, unused SDKs removed.
  • M3: permissions checked on the server, tokens revoked at logout.
  • M4: deep link, intent and WebView inputs checked against an allowlist.
  • M5: cleartext disabled, pinning works, SSL errors are not ignored.
  • M6: no personal data in logs or analytics, minimal permissions.
  • M7: RASP (root/jailbreak, emulator, hook, debugger, tamper), obfuscation enabled.
  • M8: no debuggable, allowBackup="false", exported components justified.
  • M9: secrets in Keystore/Keychain, everything cleared on logout.
  • M10: modern algorithms, no keys in code, random IV.

Conclusion

The OWASP Mobile Top 10 (2024) breaks app security down into ten clear questions. Almost every finding in a review report falls into one of these categories, so going through the list item by item before the review is the most reliable way to reduce the number of findings. In our experience, M7 and M9 are the ones most often missed: they are not planned in a normal development process, yet the expert checks them first. For an overview of the process, see what a mobile app security review checks.

If you want to go through your app from M1 to M10 before the review, request a security scan. The Claude AI agent quickly analyses the code, manifest and binary, and our specialist confirms each finding on a device and helps you close it.