Lesson 1 of 6 · 10 min read
The Mobile Platform Security Model
In this lesson
TL;DR: Each app runs in a sandbox with its own identity and private storage. Its signature is its identity for updates and trust between apps. Permissions and entitlements gate sensitive resources. Hardware-backed storage keeps keys from being copied off the device. These protect apps from each other. A modified app or compromised OS can defeat many app-local checks. That does not mean physical possession alone exposes a locked device, or that OS compromise necessarily extracts a hardware-protected key. Specify the attacker's access, and keep service authorization on the server.
Before you read
Pick an answer before you read further. The lesson below explains it, and guessing first, right or wrong, helps the explanation stay with you.
1A developer moves an API key from Java code into a C library inside the Android app, saying the key is now protected by the sandbox. Is it?
Four mechanisms, on both platforms
| Mechanism | Android | iOS |
|---|---|---|
| Isolation | Each app gets its own Linux UID; SELinux confines app domains | Kernel-enforced sandbox profile per app container |
| Identity | APK signature: decides updates and signature-level permissions | Code signature checked at load and on every executable page |
| Authority | Normal, dangerous (runtime), signature and special permissions | Entitlements in the signature, plus user permission prompts |
| Key storage | Android Keystore in a TEE or StrongBox chip | Keychain; Secure Enclave for keys that never leave hardware |
On top of these, both platforms apply exploit mitigations (ASLR, non-executable memory, control-flow protections, pointer authentication on recent Apple devices) and verified boot.
Android isolation in numbers
Android's sandbox is the Linux user model repurposed: every app is a different "user". The numbers make the mechanism concrete, and interviewers like candidates who can reason with them.
- App UIDs are allocated from 10000 to 19999. An app with app ID 123 runs as UID 10123, shown as
u0_a123. - Each Android user (a secondary user, or a work profile) adds 100000. The same app installed in a work profile with user ID 10 runs as 10 × 100000 + 10123 = 1,010,123, shown as
u10_a123, with a separate data directory. - Isolated processes (a service declared
isolatedProcess, or a WebView renderer) get UIDs from 90000 upwards with no permissions at all, so code that parses untrusted content can run with less authority than the app itself. - Private data directories have been mode 700 for apps targeting API 24 and later (they were 751 before), so other UIDs cannot even list them.
UIDs are discretionary access control: the kernel checks file ownership. SELinux adds mandatory access control on top. It was permissive in Android 4.3, partially enforced in 4.4 and fully enforced from 5.0. In 5.0 all third-party apps shared one SELinux domain and relied on UIDs to separate them; from Android 9, apps targeting API 28 and later get an individual SELinux sandbox, and making app data world-accessible is no longer allowed. Android 8.0 added a seccomp-bpf filter for all apps, removing system calls that apps never legitimately need, which shrinks the kernel attack surface an app-level exploit can reach.
- 1
1 · Per-app Linux UID
10000 to 19999, plus 100000 per user
- Kernel checks file ownership
- Data directory mode 700
Stops: another app reading private files
plus - 2
2 · SELinux, per-app category
enforced since 5.0; per app since 9
- Mandatory, not set by the app
- Separates apps from each other and from system services
Stops: a bug that loosens file permissions
plus - 3
3 · seccomp-bpf filter
all apps since 8.0
- Unneeded system calls are blocked
- Less kernel reachable from an app exploit
Shrinks: the path from app bug to kernel bug
plus - 4
4 · Permissions and app ops
install-time, runtime, special
- Gate platform resources
- User can revoke at any time
Stops: silent access to camera, location, contacts
plus - 5
5 · Keystore in TEE or StrongBox
keys never enter the app process
- Usable, not exportable
- Check hardware security level
Stops: keys copied off the device
Identity and ownership
Every app is a separate Linux user, so ordinary file permissions keep apps apart.
The Android permission model
Permissions gate access to platform resources. They come in three kinds, and the difference matters in an interview:
| Kind | Protection level | Granted | Examples |
|---|---|---|---|
| Install-time | normal | Automatically at install | Internet access, vibration |
| Install-time | signature | Only to apps signed with the same certificate as the app or platform that defines the permission | A bank's own SDK talking to its companion app |
| Runtime | dangerous | By the user, in a dialog, at the moment of use (Android 6.0 and later) | Camera, microphone, location, contacts |
| Special | appop | By the user, in a settings screen | Draw over other apps, accessibility services, install unknown apps |
The runtime model has accumulated user protections that change what an app can rely on:
- A user who denies a runtime permission twice is not asked again; the app must send them to settings.
- Android 11 added one-time grants for location, microphone and camera, and revoking any permission kills the app's process.
- Apps targeting API 30 and later that go unused for a few months have their runtime permissions reset; Android 12's hibernation also stops background work. Google backported the reset to Android 6.0 to 10 devices through Play services from December 2021.
- Since Android 10, background location is a separate permission; since Android 12, users can grant approximate location (accurate to about 3 square kilometres) instead of precise.
- Since Android 11, apps see a filtered list of installed apps unless they declare what they need with
<queries>; the all-packages permission requires Google Play approval because the list of installed apps is personal data.
The special permissions are where mobile fraud lives. Banking trojans usually arrive by sideloading, then talk the user into enabling an accessibility service (which can read the screen and perform taps) or drawing over other apps (which can show a fake login on top of the real one). Neither is a runtime dialog, and both give an app power over other apps. That is why the defence moves to the server: step-up checks for risky transactions, and risk signals such as Play Integrity's app-access verdict, which reports whether apps that can capture or control the screen are running.
One more permission detail candidates miss: permissions do not protect your app's components. An exported activity, service or content provider is callable by any app unless it is unexported or protected by a permission the caller must hold, ideally a signature permission. That is the subject of the IPC and deep links lesson.
iOS: signing, entitlements and the sandbox
iOS enforces more of the model in the kernel and leaves fewer choices to the app:
- Every executable page must be signed with an Apple-issued certificate, checked at load and as pages are brought into memory. Memory that is both writable and executable is only available with a dynamic code-signing entitlement that Apple grants to its own components such as Safari's JavaScript JIT. That is why third-party apps cannot generate native code at runtime: the kernel refuses, not the App Store.
- Library validation means a process may only load system libraries or libraries signed with the same 10-character Team ID, so injecting a library from another developer fails on a stock device.
- Entitlements are signed key-value pairs inside the code signature: access to the Keychain groups, iCloud containers, push notifications, app groups. They cannot be changed without breaking the signature.
- The sandbox gives each app a unique home directory, randomly assigned at install, and runs third-party apps as the non-privileged
mobileuser on a read-only system partition. - Enterprise distribution (in-house apps signed with an enterprise certificate) requires positive confirmation from Apple on first launch, so a revoked enterprise certificate stops its apps launching.
The Secure Enclave, present in every iPhone since the iPhone 5s, is a separate processor running its own L4-based operating system. It holds a per-device UID key fused at manufacture that no software, debugger or JTAG connection can read, and it enforces passcode attempt limits in hardware. Keys created in it with the right flags can be used by the app but never exported, which is what makes device binding possible.
Signing keys are the app's identity
On both platforms, the signing key decides who may update an app. On Android, an update is installed only if it is signed with the same key, or with a key the previous one authorised through rotation. APK signature scheme v2 arrived in Android 7.0, v3 in Android 9 added a signed key-rotation lineage, v4 in Android 11 supports incremental installs and v3.1 in Android 13 refined rotation. A stolen signing key lets an attacker ship an update that inherits the app's data and its signature-level permissions on every device that installs it. Google Play App Signing, where Google holds the app signing key and the developer holds an upload key, exists so that losing the developer's key is recoverable.
Where the platforms differ in ways that change a threat model
- Distribution. Android allows installing apps from outside Google Play, which is how most Android banking malware arrives, usually after persuading users to grant accessibility or overlay permissions. iOS distribution is controlled by Apple by default, with alternative marketplaces now allowed in some regions.
- Updates. Android security updates depend on device makers and carriers, so an app sees users across many patch levels; iOS updates reach most supported devices quickly.
- IPC. Android offers rich inter-app communication (intents, services, content providers) that apps expose deliberately and often by mistake. iOS offers narrower channels (URL schemes, universal links, extensions, app groups).
- Dynamic code. iOS generally prevents apps generating executable code at runtime; Android allows loading code dynamically.
The boundary that does not exist
Protecting: tokens, keys and logic inside the app
- 1
1 · App sandbox
UID or sandbox profile
- Stops: another app reading private files
- Fails: device owner with root or a jailbreak
- 2
2 · Hardware-backed keys
non-exportable
- Stops: key copied off the device
- Fails: malware using the key on the device
- 3
3 · Obfuscation and anti-tamper
raises effort only
- Slows: reverse engineering and patching
- Fails: a determined analyst, eventually
- 4
4 · Server-side authorization and limits
decides regardless of client
- Stops: device owner reading or patching the app
- Stops: custom client calling the API directly
Protection from other apps
The sandbox is a strong boundary between apps on an unmodified device.
The device owner can unlock the bootloader and root an Android phone, or jailbreak an iPhone, and then read any app's files, attach instrumentation, change function results and repackage the app. Even without root, the app package itself can be decompiled. So:
- Nothing shipped in the app is secret: keys, endpoints, prompts, models, business logic.
- Nothing decided only in the app is enforced: limits, entitlements, "device is safe" flags.
- Hardware-backed keys still matter: they cannot be copied to another device, so they can bind a session to a device.
Worked example: where each control lives
A payments app lets users send money.
| Control | Lives on | Why |
|---|---|---|
| Refresh token storage | Device (Keychain or Keystore-encrypted) | Protects against theft from a lost device and other apps |
| Device-bound signing key | Device hardware | Binds approvals to this phone; cannot be copied |
| Confirmation screen with payee and amount | Device UI | The human checks what is being signed |
| Verification of the signature, limits, payee risk, fraud score | Server | The device owner cannot change these |
| Root and tamper signals | Device to server | A risk input, not a decision |
Worked example: one app, two profiles, one root
A phone has a personal profile (user 0) and a work profile (user 10). A banking app is installed in both and gets app ID 123.
| Question | Answer from the mechanism |
|---|---|
| What UIDs do the two copies run as? | 10123 (u0_a123) and 1,010,123 (u10_a123) |
| Can the work copy read the personal copy's data? | No: different UID, mode 700 directories, separate SELinux categories |
| Where does the WebView inside the app render untrusted pages? | In an isolated process with a UID from 90000 up and no permissions |
| Can a lookalike app with the same package name get the bank's signature permission? | No: signature permissions follow the signing certificate, not the name |
| Can a malicious app with accessibility enabled read the bank's screen? | Yes: that special permission is power over other apps, granted by the user |
| Can the device owner who unlocked the bootloader and rooted the phone read everything? | Yes: root bypasses UID checks and can disable SELinux; the hardware keys still cannot be exported |
The last two rows are the interview: the sandbox is strong between apps, the user can grant one app power over another, and the owner can defeat everything except hardware key custody and the server.
Misconceptions interviewers listen for
- "Android permissions protect my app's components." They gate platform resources. Components need
exported=falseor a permission on the component itself. - "SELinux is the same as the UID sandbox." It is a second, mandatory layer that the app cannot loosen, and since Android 9 it separates apps from each other too.
- "iOS apps can't run dynamic code because of App Store rules." The kernel enforces it: no writable and executable memory without an entitlement only Apple grants.
- "The sandbox protects the app from root." It protects apps from each other.
- "A runtime permission, once granted, stays granted." One-time grants, auto-reset after months of non-use and user revocation all remove it.
What if · interview follow-ups
Hold your answer as the constraints change
You are threat-modelling a mobile banking app that ships on Android and iOS. The interviewer starts with the platform defaults and then changes one assumption at a time.
Start here
What if another app on the same phone tries to read the banking app's stored refresh token?
Which layers sit between two apps on an unmodified device?
On Android the other app runs under a different UID, cannot list the 700-mode data directory, and is confined by its own SELinux category; on iOS the kernel sandbox profile and the randomised container do the same. The token is safe from other apps by default, provided the bank did not export a content provider or write the token to shared storage, logs or the clipboard.
Carry it forwardThe mobile sandbox is a strong app-to-app boundary; leaks come from what the app deliberately or accidentally shares.
Weak answerProposing encryption with a key stored in the same app as the main defence against other apps.
Constraint changes
What if the other app is malware the user sideloaded and granted the accessibility service?
Is accessibility a permission over the platform or over other apps?
Accessibility lets it read the screen and perform taps in other apps, so it can watch the banking app and drive it, even though it cannot read the app's files. The sandbox is intact and irrelevant. The defences are server-side: step-up authentication and transaction confirmation for risky actions, behavioural fraud signals, and platform signals such as the Play Integrity app-access verdict that reports screen-capturing or controlling apps.
Carry it forwardSpecial permissions give one app power over others; assume a user can be talked into granting them and design server checks for it.
Weak answerClaiming the sandbox stops screen-reading malware.
Constraint changes
What if two of the bank's own apps need to share data?
What does Android trust: the package name or the signing key?
Use a component protected by a signature-level permission, which Android grants only to apps signed with the same certificate, or on iOS a shared Keychain access group or app group, which requires the same developer team's entitlements. The signing key is the trust anchor, so its custody is part of the security of both apps; Play App Signing reduces the risk of losing it.
Carry it forwardPlatform trust between apps follows signing identity; protect the key like a production credential.
Weak answerChecking the caller's package name, which any app can claim before installation.
Constraint changes
What if a kernel vulnerability lets an app gain root?
Who enforces UIDs and SELinux?
The kernel enforces both, so both fall: the attacker can read every app's data and patch running processes. What survives is key material in the TEE, StrongBox or Secure Enclave, which can be used but not exported, and the server. Hardware-backed key attestation and device-integrity verdicts can report that the boot state is no longer verified, so the server can lower trust or require re-enrolment.
Carry it forwardWhen the OS falls, only hardware key custody and server-side decisions remain.
Weak answerRelying on in-app root detection as the control for a kernel compromise.
Constraint changes
What if a large share of your users are on old Android versions?
Which protections arrived in which release?
Devices before Android 9 have no per-app SELinux sandbox, devices before 11 have no one-time permissions or package visibility filtering, and old devices may lack hardware-backed attestation or current security patches. Treat their device signals as weaker, push decisions server-side, consider requiring a minimum version for high-risk features, and measure the population before deciding.
Carry it forwardA mobile threat model is per OS version; know which protections your users actually have.
Weak answerDescribing the latest Android security model as if every user had it.
Now defend it
As the defender, what would you log server-side to see platform-level abuse?
Attestation and integrity verdicts per session with the OS version and patch level, device-key identifiers so you can see one key used from many places or many accounts on one device, risky transactions with their step-up outcome, and signals of screen-controlling apps where the platform provides them. The server sees every request, so it is where platform weaknesses become visible patterns.
Primary references
References for the mechanisms discussed above, accessed 6 November 2026:
How this shows up in interviews
"Compare Android and iOS security", "how does the Android sandbox work", "threat-model a mobile banking app" and "is it safe to hide a key in native code" all test the same idea: name what the platform guarantees between apps, then refuse to rely on the client against its own user.
Say it in 30 seconds: "Both platforms sandbox each app, identify it by signature, gate resources with permissions or entitlements and give us hardware-backed key storage. That protects apps from each other. It doesn't protect an app from the person holding the phone, who can root it, read everything and patch the logic. So I treat the app as a public client: nothing shipped is secret, nothing decided locally is enforced, hardware keys bind sessions to devices, and the server makes every decision that matters."
Check yourself
Say or write your answer first, then reveal. Explaining it from memory, in your own words, is the skill an interviewer is checking.
1What does an app's signing key control on Android, and why must it be protected?
2Why is a hardware-backed key still useful if a rooted device's owner can control the app?
3An Android app with app ID 57 is installed in a work profile whose user ID is 10. What UID does it run as, and why does that matter?
4What is the difference between a dangerous permission and a special (appop) permission on Android?
5Why can't a third-party iOS app include a JIT compiler that generates native code?