Determine if running on a rooted device
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
On Android, you cannot prove with perfect certainty that a device is not rooted from inside the app. What you can do is collect signals that strongly suggest root access or system tampering. In practice, good root detection is layered: use several heuristics, treat the result as risk scoring, and avoid pretending it is mathematically airtight.
Why Root Detection Is Imperfect
Rooted users control the device more than the app does. That means they can:
- hide binaries
- patch system properties
- hook your code
- fake filesystem checks
So the honest goal is not perfect detection. The real goal is to raise the bar and make integrity checks meaningful enough for your threat model.
Common Root Indicators
Typical checks include:
- presence of
subinaries - presence of root-management apps such as Magisk or SuperSU
- writable system partitions in suspicious places
- dangerous test build tags such as
test-keys - successful execution of privileged shell commands
None of these is individually conclusive. Together, they form a stronger signal.
Example Heuristic In Kotlin
Here is a small Kotlin example that combines several basic checks.
This is not bulletproof, but it is a reasonable baseline.
Add Runtime Command Checks Carefully
Some apps also try executing shell commands such as which su.
This can catch devices where the su binary is present on the path. But it is still only one signal, and on some devices the command itself may not exist.
Prefer Integrity Services For High-Risk Apps
If your app handles sensitive actions such as payments or anti-cheat enforcement, local heuristics alone are usually not enough. You should also use platform-backed integrity services when available.
The basic pattern is:
- run local root and tamper heuristics
- request a device-integrity attestation from a trusted service
- make server-side decisions based on combined evidence
That is stronger than trusting an on-device check in isolation.
What To Do When You Detect Root
Detection is only half the problem. Decide your response deliberately.
Options include:
- log and continue with reduced trust
- block only sensitive features
- require server-side review
- deny execution for high-risk workflows
A blanket hard stop may be appropriate for banking or DRM use cases, but not every app needs that policy.
Common Pitfalls
A common mistake is trusting one check such as the existence of /system/bin/su and calling root detection solved. Modern root-hiding tools can bypass simplistic checks easily.
Another issue is making security decisions entirely on-device. If the attacker controls the device, local-only enforcement is fragile.
Developers also sometimes crash or block too aggressively on uncertain signals such as test-keys, which may appear on development builds or custom ROMs without the exact threat the app cares about.
Finally, do not promise users or auditors that your app can infallibly detect rooted devices. That claim is stronger than what the platform realistically allows.
Summary
- Root detection on Android is heuristic, not perfect proof.
- Use several signals such as
subinaries, root packages, and build tags instead of relying on one check. - Treat root status as a risk signal and align your response with the application's threat model.
- For high-risk apps, combine local checks with stronger integrity or attestation mechanisms.
- Focus on layered defense rather than pretending a single on-device check can be unbeatable.

