The Android platform takes advantage of the Linux user-based protection to identify and isolate app resources. This isolates apps from each other and protects apps and the system from malicious apps. To do this, Android assigns a unique user ID (UID) to each Android application and runs it in its own process.
Android uses this UID to set up a kernel-level Application Sandbox. The kernel enforces security between apps and the system at the process level through standard Linux facilities, such as user and group IDs that are assigned to apps. By default, apps can't interact with each other and have limited access to the operating system. For example, if application A tries to do something malicious, such as read application B's data or dial the phone without permission (which is a separate application), then the operating system protects against this behavior because application A does not have the appropriate user privileges. The sandbox is simple, auditable, and based on decades-old UNIX-style user separation of processes and file permissions.
Because the Application Sandbox is in the kernel, this security model extends to native code and to operating system applications. All of the software above the kernel, such as operating system libraries, application framework, application runtime, and all applications, run within the Application Sandbox. On some platforms, developers are constrained to a specific development framework, set of APIs, or language in order to enforce security. On Android, there are no restrictions on how an application can be written that are required to enforce security; in this respect, native code is as sandboxed as interpreted code.
Generally, to break out of the Application Sandbox in a properly configured device, one must compromise the security of the Linux kernel. However, similar to other security features, individual protections enforcing the application sandbox are not invulnerable, so defense-in-depth is important to prevent single vulnerabilities from leading to compromise of the OS or other apps.
Android relies on a number of protections to enforce the application sandbox. These enforcements have been introduced over time and have significantly strengthened the original UID-based discretionary access control (DAC) sandbox. Previous Android releases included the following protections:
- In Android 5.0, SELinux provided mandatory access control (MAC) separation between the system and apps. However, all third-party apps ran within the same SELinux context so inter-app isolation was primarily enforced by UID DAC.
- In Android 6.0, the SELinux sandbox was extended to isolate apps across
the per-physical-user boundary. In addition, Android also set safer defaults
for application data: For apps with
targetSdkVersion >= 24, default DAC permissions on an app's home dir changed from 751 to 700. This provided safer default for private app data (although apps may override these defaults).
- In Android 8.0, all apps were set to run with a
seccomp-bpffilter that limited the syscalls that apps were allowed to use, thus strengthening the app/kernel boundary.
- In Android 9 all non-privileged apps with
targetSdkVersion >= 28must run in individual SELinux sandboxes, providing MAC on a per-app basis. This protection improves app separation, prevents overriding safe defaults, and (most significantly) prevents apps from making their data world accessible.
Guidelines for sharing files
Setting app data as world accessible is a poor security practice as access is
granted to everyone and there is no way to limit access to only the intended
recipient(s). This practice has led to information disclosure leaks, confused
deputy vulnerabilities, and is a favorite target for malware that targets apps
with sensitive data (such as email clients). In Android 9 and higher, sharing
files this way is explicitly disallowed for apps with
Instead of making app data world-accessible, use the following guidelines when sharing files:
- If your app needs to share files with another app, use a content provider or shared location on external storage. Content providers share data with the proper granularity and without the many downsides of world-accessible UNIX permissions (for details, refer to Content provider basics).
- If your app has files that genuinely should be accessible to the world (such as photos), use external storage. For help, refer to Save file to public directory.