Mobile apps are attractive targets. They run on devices users carry everywhere, they handle authentication credentials, payment information, and personal data, and they're often developed under time pressure that pushes security testing to the bottom of the backlog. This is a practical guide to the vulnerabilities that consistently appear in mobile app security audits — and how to fix them before the audit finds them.
Why Mobile Security Is Often Under-Resourced
Web security has a well-established culture of penetration testing, code review, and security headers. Mobile security is younger and the tooling is less standardised. Many development teams apply web security thinking to mobile apps — they focus on API security and largely ignore the client-side attack surface. The OWASP Mobile Security Testing Guide documents this surface comprehensively. Here are the ten most impactful findings.
1. Insecure Data Storage
The problem: Sensitive data (auth tokens, personal information, PII) stored in plain text in SharedPreferences (Android), NSUserDefaults (iOS), SQLite without encryption, or log files.
The fix: Use the Android Keystore System or iOS Secure Enclave for cryptographic keys. For sensitive user data, use EncryptedSharedPreferences (Android) or the Keychain (iOS). Never log sensitive data. Assume any file on device storage can be read by a rooted/jailbroken device.
2. Insecure Communication
The problem: Plain HTTP connections, disabled certificate validation (the developer added this "temporarily" during testing and it shipped to production), or weak TLS configurations that allow downgrade attacks.
The fix: Enforce TLS 1.2+ for all connections. Implement certificate pinning for your own API endpoints. Never ship code with certificate validation disabled. Use Android's Network Security Config to enforce cleartext traffic blocks.
3. Weak Authentication
The problem: No biometric authentication option, passwords stored in a recoverable format, no account lockout after failed attempts, or authentication state stored only in client-accessible storage.
The fix: Implement biometric authentication using the platform's Biometric API. Issue short-lived access tokens (15–60 minutes) with refresh tokens that have their own expiry. Store tokens in the Keychain/Keystore, not NSUserDefaults/SharedPreferences. Enforce account lockout server-side — never client-side only.
4. Insecure Authorisation
The problem: The app enforces access control only on the client side. A user who intercepts API calls can access resources belonging to other users by changing an ID in the request.
The fix: All authorisation logic must be enforced server-side. The API should validate that the authenticated user has permission to access the requested resource on every request. Client-side access control (hiding buttons, disabling menus) is a UX feature, not a security control.
5. Insufficient Cryptography
The problem: Using deprecated algorithms (MD5, SHA-1 for passwords, DES, RC4), rolling custom crypto, storing encryption keys alongside the encrypted data, or using a hardcoded IV.
The fix: For password hashing, use bcrypt, Argon2, or PBKDF2 with appropriate cost factors. For symmetric encryption, use AES-256-GCM with a random IV per encryption operation. Never write your own cryptographic primitives. Use the platform's cryptographic APIs — they've been audited.
6. Privacy Leakage via Logs and Clipboard
The problem: Verbose logging in production builds leaks API responses, user data, and error details to device logs. Copy-paste clipboard contents are accessible to any app on the device.
The fix: Strip or redact all debug/verbose logging in production builds. On iOS, use UIPasteboard expiration so clipboard contents clear after 120 seconds. On Android, mark sensitive text fields with InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS and disable clipboard for password fields.
7. Code Tampering and Reverse Engineering
The problem: Apps can be decompiled, modified, and repackaged. Attackers can bypass premium feature checks, remove ads, extract API keys, or modify app behaviour to bypass security controls.
The fix: Enable ProGuard/R8 code obfuscation (Android) and enable bitcode stripping (iOS). Implement root/jailbreak detection — not as a hard block (which users resent) but as a risk signal. Move sensitive business logic server-side where it cannot be tampered with. Use Android's Play Integrity API to verify the app hasn't been tampered with.
8. Exposed Components and Intents
The problem: Android Activities, Services, or ContentProviders marked as exported="true" without proper permission checks can be invoked by malicious apps on the same device.
The fix: Audit your AndroidManifest.xml. Set exported="false" on every component that doesn't need to be accessible from outside your app. For components that do need to be exported, add custom permissions and validate all data received via Intents — treat them as untrusted input.
9. Hardcoded Secrets
The problem: API keys, database passwords, and third-party service credentials embedded directly in source code or configuration files shipped with the app binary. These are trivially extracted from the APK/IPA.
The fix: No secrets in the app binary, full stop. Use environment-specific remote configuration or a secrets API that requires authentication to fetch. For truly sensitive operations (payment processing, user data access), the app should authenticate to your server which then makes the privileged call — never give a mobile app direct access to sensitive backends.
10. Insecure WebView Configuration
The problem: WebViews with JavaScript enabled and file access turned on, loading untrusted URLs, or exposing native bridges to JavaScript without origin validation. This can allow JavaScript injection that accesses device APIs.
The fix: Disable file access in WebViews (setAllowFileAccess(false)). Only load URLs from your own trusted origins — validate origin before any JavaScript bridge call. Use @JavascriptInterface annotations sparingly and validate all data passed from JavaScript. Enable Safe Browsing API to protect against malicious URLs.
Making Security a Habit, Not an Audit
The most effective security practice is shifting left — catching issues in development rather than penetration testing. Add a mobile security checklist to your PR template. Run MobSF (Mobile Security Framework) as part of your CI pipeline — it catches most of the issues above automatically. Schedule an annual manual penetration test for your most sensitive apps.
Security is not a feature you add. It's a property you build in from the start.