Android sandboxing is a security mechanism that prevents one app from freely accessing another app's private data or interfering with its execution.
For example, suppose you install WhatsApp, Instagram, and a banking app on your phone. All three apps run on the same Android operating system, use the same hardware, and may communicate with system services.
Yet Instagram should not be able to open WhatsApp's private message database, and WhatsApp should not be able to read your banking app's private files.
Android's application sandbox provides the underlying isolation that makes this possible. It is enforced primarily through Linux-level security mechanisms, with additional protections from SELinux and Android's permission system.
What does a sandbox mean?
Imagine three people working in separate locked rooms inside one building.
Room A: WhatsApp
Room B: Instagram
Room C: Banking AppAll three rooms are inside the same building, just as all three apps runs on the same phone.
The rooms represent security boundaries, not separate physical phones.
Android allows apps to use shared resources through controlled mechanisms, but an app doesn't automatically get access to another app's private data just because both apps are installed on the same device.
How does Android actually implement sandboxing?
The key is that Android does not rely on just one security feature.
Multiple mechanisms work together.
1 Linux UID – each app gets its own operating-system identity
This is one of the most fundamental parts of of the Android sandbox.
UID stands for User Identifier. Linux uses it to identify the user under which a process runs.
When Android installs an application, it assigns the app a Linux identity for a given Android user or profile. Apps that aren't explicitly permitted to share an identity run under separate app identities.
For example, imagine these illustrative UIDs:
| Application | Example UID |
| 10241 | |
| 10272 | |
| Banking App | 10305 |
These numbers are examples, not actual UIDs from the phone.
When WhatsApp runs, its process operates under its assigned identity. Instagram uses its own identity.
Linux checks that identity when the process attempts to access files protocted by ordinary file ownership and permissions.
2 File permissions – private files belong to the app
An Android app commonly stores private files in a location like:
/data/user/0/com.example.app/
├── files/
├── cache/
├── databases/
└── shared_prefs/Conceptually, the directory is owned and protected so the app can access its private data while unrelated apps cannot access it through ordinary filesystem operations. Android's security guidance recommends using internal app storage for private data.
Imagine the directory has restrictive permissions similar to 0700, meaning only the owner can read, write, and traverse it.
App A's UID → can access App A's private files
App B's UID → cannot normally access App A's private filesThe kernel enforces the applicable file permissions. A normal app cannot simply claim to be another app's UID.
3 SELinux – another layer of access control
Linux UIDs and file operations are not the whole story.
Android also uses SELinux, which stands for Security-Enhanced Linux.
SELinux applies mandatory access control (MAC). It uses security policies to define which processes can acces which resources.
Android's SELinux policies follow a default-deny approach: operations not explicitly allowed by the applicable policy are denied.
Think about the difference this way:
- UID and file permissions: Does this process's identity have ordinary permission to access this file?
- SELinux: Does the applicable security policy allow this process to perform this action on this resource?
Both checks can matter.
4 Restricted system calls
Apps ultimately uses Linux system calls to perform operations such as opening files, creating processes and communicating with the operating system.
Android adds further protection through mechanisms such as seccomp-BPF, which can restrict the system calls available to application processes. This reduces the kernel attack surface exposed to an app.
UID and GID
UID identifies which user a process runs as. GID identifies the group or groups that process belongs to. Android uses these Linux concepts to control which files, directories, and other resources a process can access.
The problem UID and GID solve
Imagine your Samsung phone has three apps:
- Chrome
- Proton Mail
- A banking app
Each app stores private data. If every app ran under the same operating-system identity, it would be much harder to isolate their files from one another.
Linux solves this problem using user and group identities.
Chrome: UID: 10241, GID membership: illustrative
Proton Main: UID: 10272, GID membership: illustrative
Banking app: UID: 10305, GID membership: illustrativeBecause these apps normally run under separate Linux UIDs, one app cannot simply access another app's private files. Linux checks the caller's identity against the applicable access-control rules.
What exactly is a UID?
UID stands for User Identifier.
Linux assigns each running process a user identity. The identity represented internally by a number.
For example:
UID 0 -> root (superuser)
UID 1000 -> commonly system on Android
UID 2000 -> commonly shell on Android
UID 10241 -> illustrative application UIDThe key idea is that the kernel checks the process's UID when enforcing many access-control rules.
Try it on your phone:
From your Windows terminal, run:
adb shell idC:\>adb shell id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:shell:s0This tells us the command is executing under the shell user identity rather than automatically running as root.
Now run:
adb shellThen:
su
idOutput:
C:\>adb shell
greatlte:/ $ su
greatlte:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:eftsu:s0
greatlte:/ #If su successfully switches to root, you should see a UID of 0.
What exactly is a GID?
GID stands for Group Identifier.
Linux groups allows multiple users or processes to receive shares access to particular resources without giving them all the same UID.
For example, imagine a file with these ownership and permission details:
-rw-r----- alice developers report.txtConceptually, this means:
- The owner, alice, can read and write.
- Members of the
developersgroup can read. - Other users have no access through these permission bits.
Android uses the same general Linux ownership and permission model, although actual Android identities and policies are more complex.
Important: A GID is not an app's package ID. The package name, UID and GID are different concepts.
How UID and GUID protect /data/data
/data/data/
├── com.android.chrome/
├── ch.protonmail.android/
├── com.Dominos/
└── ...Conceptually, Android protects each app's private directory using ownership, filesystem permissions and additional security policies.
Suppose two applications have these illustrative identities:
Chrome process
UID = 10241
|
v
/data/data/com.android.chrome/
Proton Mail process
UID = 10272
|
v
/data/data/ch.protonmail.android/When Chrome attempts to open Proton Mail's private database, Linux checks whether Chrome's process identity is allowed to access the file.
If the file is restricted to Proton Mail's identity, Chrome is denied.
Chrome attempts to read Proton Mail's database
|
v
Kernel checks access
|
v
Permission deniedThe application doesn't need to implement this protection itself. The operating system enforces it.
This is why an app cannot bypass the sandbox simply by writing code that opens another app's private path.
What Changes when you run su?
In your earlier experiment, you ran:
su
ls /data/data/After switching to root, you could simply list many application directories.
The key change was your process identity:
Ordinary shell
UID = 2000 (commonly)
|
v
Access to /data denied
su
Root shell
UID = 0
|
v
Broader filesystem accessRoot is privileged Linux identity. It can bypass many ordinary filesystem permission checks that restrict normal users.
However, Android also uses SELinux mandatory access control. Depending on the root configuration and SELinux policy, even a root process may still be restricted from certain operations.



Join the discussion
Sign in with your account to post comments, reply to others, and participate in the conversation.
Login to Comment