Mobile App
18 practices · OWASP MASVS — Storage, Crypto, Auth, Network, Platform, Code, Resilience, Privacy
React Native and native builds: what goes in the binary, where tokens live, how traffic is protected, and what a release build must not still contain.
Ticking these off for a specific project? The Project Security Checklist tracks all nine categories in one place. For why these patterns keep recurring, see Security Best Practices.
1. No Hardcoded Secrets in the Binary
DescriptionAPI keys, signing credentials, and encryption keys never live in source code that ships inside the app binary — anyone can decompile an APK or IPA and read every string in it.
Example// Never: const API_KEY = 'sk_live_abc123'
// Instead: fetch a short-lived token from your backend
// at runtime, scoped and expiring
2. Platform Secure Storage
DescriptionStore tokens and sensitive data in iOS Keychain or Android Keystore, which are hardware-backed and OS-protected — never a static encryption key or a shared MMKV/SharedPreferences secret baked into the app.
ExampleiOS: kSecClassGenericPassword + kSecAttrAccessible
Android: EncryptedSharedPreferences with a MasterKey
3. Exclude Sensitive Data From Backups
DescriptionDevice backups (iCloud, Android auto-backup) can leave sensitive local files on a third party's servers — explicitly exclude anything sensitive from the backup manifest.
ExampleiOS: NSURLIsExcludedFromBackupKey = true on sensitive files
Android: android:allowBackup="false" or a backup rules XML
4. Deep Link & URL Scheme Validation
DescriptionValidate every deep link and universal/app link against an allowlist before acting on it — including query parameters — since deep links are a common vector for auth bypass and phishing redirects.
Exampleif (!ALLOWED_HOSTS.has(url.host)) return // reject
// verify universal-link association, not just a custom scheme
5. Minimal, Justified Permissions
DescriptionRequest only the OS permissions the current feature actually needs, at the point of need (not all at install) — every permission granted is additional attack surface and a privacy question.
ExampleRequest CAMERA permission only when the user taps
"Scan QR code" — not on app launch
6. Session Expiry & Step-Up Authentication
DescriptionAccess tokens expire and refresh silently for normal use, but sensitive actions (changing a password, adding a payout method) require re-authentication even within an active session.
ExampleViewing balance: cached session OK
Adding bank account: force re-auth (biometric/password)
7. Scrub Sensitive Data From Logs & Screenshots
DescriptionDisable verbose logging in release builds, and blank the screen in the app-switcher/recents view for screens showing balances, PII, or payment details.
ExampleAndroid: FLAG_SECURE on sensitive Activities
iOS: overlay a blank view in applicationDidEnterBackground
8. Vetted Cryptography, Proper Key Management
DescriptionUse the platform's audited crypto libraries (not a hand-rolled cipher), with keys generated and stored via the secure enclave/hardware keystore rather than embedded as constants.
ExampleAndroid: KeyGenParameterSpec with setIsStrongBoxBacked(true)
when available — not a static byte[] key in source
9. Explicit Consent Before Analytics/Tracking
DescriptionAnalytics and crash-reporting SDKs (Mixpanel, Sentry, Firebase) initialize only after explicit user consent, with PII scrubbed from event payloads and crash breadcrumbs — especially for data involving minors.
Exampleif (userConsent.analytics) { Mixpanel.init(token) }
// Sentry: beforeSend() strips email/name from context
10. CSPRNG for Anything Security-Sensitive
DescriptionOTPs, tokens, and any ID used as an authorization boundary come from a cryptographically secure random source, never Math.random() or a timestamp-derived value.
Examplecrypto.getRandomValues(new Uint8Array(16))
// not Math.random()
11. Certificate Pinning for Sensitive Traffic
DescriptionFor high-value API traffic (auth, payments), pin the expected certificate or public key so the app rejects even a validly-signed-but-unexpected certificate — defending against compromised CAs or on-path proxies.
ExampleiOS: NSPinnedDomains in Info.plist
Android: Network Security Config <pin-set>
12. Enforce TLS, No Cleartext Exceptions
DescriptionApp Transport Security is fully enforced on iOS and usesCleartextTraffic is false on Android — with no per-domain exceptions carved out for "just this one legacy API."
ExampleAndroid manifest: android:usesCleartextTraffic="false"
iOS: NSAppTransportSecurity with no NSExceptionDomains
13. Biometric Auth Backed by the Secure Enclave
DescriptionFace ID/Touch ID/fingerprint should gate access to a key stored in the secure enclave — not just show/hide a screen in app code, which a jailbroken device could bypass entirely.
ExampleiOS: LAContext + SecAccessControl with
kSecAccessControlBiometryCurrentSet, tied to a Keychain item
14. WebView Hardening
DescriptionAny WebView loading remote or CMS-sourced content disables unnecessary JS bridges, validates the origin before injecting any native bridge, and never loads arbitrary attacker-influenced URLs.
ExamplewebView.settings.javaScriptEnabled = false // unless needed
+ shouldOverrideUrlLoading() allowlist check
15. Lock Down Inter-Process Communication
DescriptionOn Android, exported Activities, Services, and Broadcast Receivers are explicitly set to android:exported="false" unless another app genuinely needs to call them, and any that are exported validate their caller.
Example<activity android:name=".AdminActivity"
android:exported="false" />
16. Dependency & SDK Vulnerability Scanning
DescriptionMobile apps bundle dozens of third-party SDKs (analytics, ads, crash reporting) — scan them for known vulnerabilities just like backend dependencies, since they run with the same permissions as your own code.
ExampleOWASP Dependency-Check / Snyk for Gradle & CocoaPods
wired into the mobile CI pipeline
17. Strip Debug Symbols From Release Builds
DescriptionRelease builds disable verbose/debug logging, strip debug symbols, and remove any developer backdoors (test endpoints, hardcoded test accounts) that made local development easier.
ExampleAndroid: minifyEnabled true + ProGuard/R8 rules
iOS: strip debug symbols in Release build settings
18. Root/Jailbreak Detection for High-Risk Apps
DescriptionFor apps handling payments or highly sensitive data, detect rooted/jailbroken devices and respond appropriately (warn, restrict features) — one layer among many, not the only defense.
ExampleCheck for su binary, Cydia, unusual system properties;
restrict payment features on a positive detection
Last updated: September 2026 · Source: Offspring — Security Best Practices.pptx (Part 4) + Security Best Practices Checklist.xlsx