Mobile Application Security
Mobile app security basics — cleartext traffic via dependencies, screenshot cache leaks, OAuth in WebView, and tamper/root/jailbreak detection.
12 questions
JuniorTheoryVery commonWhy is an API key shipped inside a mobile app binary treated as a public value?
Why is an API key shipped inside a mobile app binary treated as a public value?
Everything in the package ships to the user, so any string or key inside the installed app can be recovered from it; obfuscation raises effort but never makes a value secret. Scope a shipped key narrowly and authorize sensitive requests server-side.
Common mistakes
- ✗Assuming obfuscation or native code makes a shipped key secret
- ✗Giving a client key broader scope than its feature needs
- ✗Letting the client decide what a request is allowed to do
Follow-up questions
- →How do you scope a client key so that a leak stays low impact?
- →Where should a secret used for a partner integration actually live?
JuniorTheoryVery commonWhere should a mobile app keep auth tokens and keys, and why not in SharedPreferences?
Where should a mobile app keep auth tokens and keys, and why not in SharedPreferences?
Tokens and keys belong in the platform key store — iOS Keychain or Android Keystore — which is hardware-backed and can demand user presence. Files, SharedPreferences and plists are private only while the device is, so keep tokens out and short-lived.
Common mistakes
- ✗Treating app-private storage as safe on a rooted or jailbroken device
- ✗Putting tokens in
SharedPreferencesor a plist instead of the key store - ✗Keeping long-lived tokens on the device with no expiry or revocation
Follow-up questions
- →What does hardware-backed key storage add over an encrypted file?
- →How do you revoke a token that already sits on a lost device?
JuniorTheoryCommonThe manifest sets usesCleartextTraffic=false, but the app sends over http. Where do you look for the cause?
The manifest sets usesCleartextTraffic=false, but the app sends over http. Where do you look for the cause?
The final APK manifest and network-security-config are merged from all dependencies, so a misconfigured library can re-enable cleartext even when your manifest forbids it. Inspect every dependency's config and the merged result in the built APK — a setting holds only if it survives the build merge.
Common mistakes
- ✗Checking only your own manifest, forgetting about the dependency merge
- ✗Assuming the final APK manifest matches the source one
- ✗Not opening the built artifact to inspect the final config
Follow-up questions
- →How does the manifest merge from dependencies override your usesCleartextTraffic?
- →Why can the screenshot cache leak a password when the app is backgrounded during OTP entry?
JuniorTheoryCommonWhat do the L1 and L2 profiles of the mobile security standard MASVS mean?
What do the L1 and L2 profiles of the mobile security standard MASVS mean?
MASVS is OWASP's mobile security standard and MASTG its testing guide. L1 is the baseline any app should meet — secure storage, transport security, correct platform use. L2 adds defence in depth for sensitive apps; resilience is a separate additive set.
Common mistakes
- ✗Believing L2 replaces the L1 baseline instead of adding to it
- ✗Treating resilience requirements as a level above L2
- ✗Reading
MASVSas a certification badge rather than a requirements standard
Follow-up questions
- →Which apps genuinely need the L2 profile rather than the baseline?
- →How does the testing guide
MASTGrelate to a singleMASVSrequirement?
MiddleTheoryCommonWhat does certificate pinning add on top of ordinary TLS validation, and why is rotation hard?
What does certificate pinning add on top of ordinary TLS validation, and why is rotation hard?
TLS authenticates the server against the device trust store; pinning narrows that to your own key, so a mis-issued certificate or a CA added on the device cannot intercept traffic silently. Its cost is availability — a changed pin breaks shipped versions.
Common mistakes
- ✗Thinking pinning replaces or strengthens the TLS encryption itself
- ✗Shipping a single pin with no backup and no rotation plan
- ✗Pinning a leaf certificate that changes at every renewal
Follow-up questions
- →When is pinning worth its operational cost, and when is it not?
- →How does a backup pin let you rotate a certificate without a new release?
MiddleTheoryCommonWhich channels leak mobile app data even when your files are stored correctly?
Which channels leak mobile app data even when your files are stored correctly?
Data escapes through cloud backups, application logs, task-switcher snapshots and the clipboard. Exclude sensitive files from backup rules, keep tokens out of logs, cover the screen while the app is backgrounded, and mark sensitive fields.
Common mistakes
- ✗Assuming cloud backup never copies sensitive application files
- ✗Logging tokens or personal data in a release build
- ✗Ignoring the task-switcher snapshot and the clipboard
Follow-up questions
- →How do you exclude a credential store from platform backup?
- →Why is the task-switcher snapshot a realistic leak in a banking app?
MiddleTheoryOccasionalWhy is a biometric prompt a local user-presence check rather than authentication to your server?
Why is a biometric prompt a local user-presence check rather than authentication to your server?
The prompt returns a yes on a device you do not control, and your backend never sees the face or fingerprint, so a boolean from the client proves nothing. Bind the prompt to a key store key and sign a server challenge with it instead.
Common mistakes
- ✗Sending a biometric success boolean to the server as proof of identity
- ✗Treating user presence as a substitute for server-side authorization
- ✗Storing a key without requiring biometric unlock before it can be used
Follow-up questions
- →What should happen to a bound key when the user enrols a new fingerprint?
- →How does a signed challenge prove more than a client-side verdict?
MiddleTheoryOccasionalWhy are exported components and custom URL schemes risky, and what makes a deep link trustworthy?
Why are exported components and custom URL schemes risky, and what makes a deep link trustworthy?
An exported activity, service or receiver, and any custom URL scheme, is a public entry point another installed app can invoke, and a scheme can be claimed by more than one app. Validate every incoming intent, and prefer domain-bound links.
Common mistakes
- ✗Assuming a custom URL scheme can be claimed by only one app
- ✗Trusting parameters that arrive inside an intent or deep link
- ✗Forgetting that a component with an intent filter is reachable by other apps
Follow-up questions
- →How does domain verification make an App Link stronger than a custom scheme?
- →Where should authorization for a deep-linked screen actually be enforced?
MiddleTheoryOccasionalWhy is client-side detection of device compromise (root, jailbreak) unreliable, and how do you make bypassing it harder?
Why is client-side detection of device compromise (root, jailbreak) unreliable, and how do you make bypassing it harder?
Collect multiple tamper artifacts (root files, emulator traits, DBI hooks), sign them, and validate server-side — never trust the client verdict alone, since a DBI tool like Frida can hook the check and force it to return 'clean' (as it overrides evaluatePolicy to bypass biometrics). Obfuscate detection functions and fail silently.
Common mistakes
- ✗Trusting the client's detection verdict on a compromised device
- ✗Throwing a visible exception that points the attacker to the check's location
- ✗Relying on a single artifact without signing and server-side validation
Follow-up questions
- →How does a DBI tool override evaluatePolicy and bypass biometrics?
- →Why is failing silently on detection better than an explicit exception?
MiddleTheoryOccasionalWhat risk does a third-party SDK add to a mobile app, and how does least privilege limit it?
What risk does a third-party SDK add to a mobile app, and how does least privilege limit it?
An SDK runs inside your process with your app's identity, permissions and access to its stored data, and it ships under your name, so its bugs and its data collection become yours. Request only needed permissions, review what it sends, and pin versions.
Common mistakes
- ✗Assuming an SDK is sandboxed away from your app's data and identity
- ✗Granting a permission simply because a library asks for it
- ✗Auto-resolving library versions with no review of what changed
Follow-up questions
- →How do you find out what data an SDK actually sends off-device?
- →Why does an SDK's permission request become your app's exposure?
MiddleTheoryOccasionalHow do the risk list OWASP Mobile Top 10 and the standard MASVS differ in a security review?
How do the risk list OWASP Mobile Top 10 and the standard MASVS differ in a security review?
The Mobile Top 10 is an awareness list of recurring risks — insecure storage, insecure communication, weak authentication — useful for prioritising. MASVS turns those areas into testable requirements and MASTG says how to verify each one.
Common mistakes
- ✗Treating the Top 10 as a completion checklist
- ✗Expecting a risk list to supply testable requirements
- ✗Verifying against a risk name instead of a
MASVSrequirement
Follow-up questions
- →How would you pick a
MASVSprofile for a payments app? - →What does an insecure-communication risk look like as a testable requirement?
MiddleTheoryOccasionalWhat makes an embedded WebView risky, and how do you contain its JavaScript bridge?
What makes an embedded WebView risky, and how do you contain its JavaScript bridge?
A WebView runs remote content inside your process. A JavaScript bridge exposes native methods to that page and file access lets it reach app-private storage, so untrusted content acts with your app's identity. Load only content you control.
Common mistakes
- ✗Loading untrusted or plain-http content in an in-app
WebView - ✗Exposing broad native methods through a JavaScript bridge
- ✗Leaving file access enabled so a page can read app storage
Follow-up questions
- →Why does a bridge method need argument validation of its own?
- →When is an external browser tab a better choice than an in-app
WebView?