Android app permissions form the frontline defense between your personal data and the applications you install. With modern Android versions introducing more granular permission controls and new runtime permission categories, understanding how to audit these permissions has become essential for developers and power users who value their privacy and security.
This guide covers practical methods for auditing Android app permissions using built-in tools, ADB commands, and programmatic approaches. You’ll learn how to identify overprivileged apps, understand permission groups, and implement automated audit workflows.
Android Permission System Overview
Android organizes permissions into three protection levels that determine how users and developers interact with them:
- Normal permissions: Granted automatically at install time (e.g.,
INTERNET,ACCESS_NETWORK_STATE) - Signature permissions: Granted only if the app is signed with the same certificate as the declaring app
- Dangerous permissions: Require runtime user approval and grant access to sensitive data (e.g.,
READ_CONTACTS,ACCESS_FINE_LOCATION,CAMERA,RECORD_AUDIO)
Android 14 and the 2026 platform updates have added new permission categories including READ_MEDIA_VISUAL_USER_SELECTED for more granular photo access and improved NEARBY_WIFI_DEVICES permission for device discovery without location dependency.
Auditing Permissions via Settings
The most straightforward method for reviewing permissions uses Android’s Settings interface. Navigate to Settings > Apps, select any application, and tap Permissions to see a complete list of requested permissions grouped by category.
For a comprehensive overview of all apps with dangerous permissions, access Settings > Privacy > Permission Manager. This view groups permissions by category (Location, Camera, Microphone, Contacts, etc.) and shows which apps have access—essential for identifying apps that may no longer need certain permissions.
Modern Android versions display permission indicators in the status bar when apps actively use sensitive capabilities. A persistent camera or microphone icon warrants immediate investigation.
Using ADB for Comprehensive Audits
The Android Debug Bridge (ADB) provides powerful command-line capabilities for auditing permissions at scale. Enable developer options and USB debugging on your device, then connect via USB or wireless debugging.
Listing All App Permissions
Query all installed packages and their permissions using this command:
adb shell pm list packages -3 | while read pkg; do
echo "=== $pkg ==="
adb shell dumpsys package "$pkg" | grep -E "granted=|permission "
done
This outputs each third-party app with its permission status, including whether each dangerous permission is granted or denied.
Exporting Permission Report
Generate a complete permission inventory for analysis:
adb shell pm list packages -3 -u > packages.txt
while read pkg; do
pkg_trimmed=${pkg#package:}
echo "Package: $pkg_trimmed" >> permissions_report.txt
adb shell dumpsys package "$pkg_trimmed" | \
grep -E "runtime" | \
grep "permission" >> permissions_report.txt
done < packages.txt
Revoking Permissions via ADB
For apps you cannot uninstall but want to restrict:
adb shell pm revoke com.example.app android.permission.CAMERA
adb shell pm revoke com.example.app android.permission.RECORD_AUDIO
adb shell pm revoke com.example.app android.permission.ACCESS_FINE_LOCATION
Note that some system apps may ignore revocations. You can also reset all permissions for an app:
adb shell pm reset-permissions com.example.app
Programmatic Permission Auditing
For developers building security tools or implementing automated audits, Android provides the PackageManager API for inspecting permissions programmatically.
Reading Permissions in Android Code
val packageManager = context.packageManager
val packageInfo = packageManager.getPackageInfo(
"com.example.targetapp",
PackageManager.GET_PERMISSIONS
)
packageInfo.requestedPermissions?.forEachIndexed { index, permission ->
val isGranted = packageInfo.requestedPermissionsFlags[index] and
PackageInfo.REQUESTED_PERMISSION_GRANTED != 0
println("Permission: $permission")
println("Granted: $isGranted")
}
Permission Group Mapping
Dangerous permissions belong to permission groups. Understanding this relationship helps assess the actual access level:
val dangerousPermissions = mapOf(
"android.permission.READ_CONTACTS" to "CONTACTS",
"android.permission.WRITE_CONTACTS" to "CONTACTS",
"android.permission.GET_ACCOUNTS" to "CONTACTS",
"android.permission.ACCESS_FINE_LOCATION" to "LOCATION",
"android.permission.ACCESS_COARSE_LOCATION" to "LOCATION",
"android.permission.ACCESS_BACKGROUND_LOCATION" to "LOCATION",
"android.permission.CAMERA" to "CAMERA",
"android.permission.RECORD_AUDIO" to "MICROPHONE",
"android.permission.READ_CALENDAR" to "CALENDAR",
"android.permission.WRITE_CALENDAR" to "CALENDAR",
"android.permission.READ_SMS" to "SMS",
"android.permission.SEND_SMS" to "SMS"
)
Granting any permission within a group typically grants access to the entire group’s data. For instance, READ_CONTACTS provides access to all contacts.
Automating Permission Reviews
Creating a scheduled audit process helps maintain ongoing security. This Python script generates permission reports:
import subprocess
import json
from datetime import datetime
def get_installed_packages():
result = subprocess.run(
['adb', 'shell', 'pm', 'list', 'packages', '-3', '-f'],
capture_output=True, text=True
)
packages = []
for line in result.stdout.splitlines():
pkg = line.replace('package:', '').split('=')[0]
packages.append(pkg)
return packages
def get_package_permissions(package):
result = subprocess.run(
['adb', 'shell', 'dumpsys', 'package', package],
capture_output=True, text=True
)
permissions = []
for line in result.stdout.splitlines():
if 'android.permission.' in line and 'granted=true' in line:
perm = line.strip().split(':')[0]
permissions.append(perm)
return permissions
def generate_audit_report():
packages = get_installed_packages()
report = {
'timestamp': datetime.now().isoformat(),
'apps': []
}
for pkg in packages:
try:
perms = get_package_permissions(pkg)
if perms:
report['apps'].append({
'package': pkg,
'permissions': perms,
'count': len(perms)
})
except Exception as e:
print(f"Error processing {pkg}: {e}")
with open(f"permission_audit_{datetime.now().strftime('%Y%m%d')}.json", 'w') as f:
json.dump(report, f, indent=2)
return report
if __name__ == "__main__":
report = generate_audit_report()
print(f"Audit complete. Found {len(report['apps'])} apps with permissions.")
Run this weekly via cron or systemd timers to track permission changes over time.
Interpreting Permission Requests
Not all permissions indicate malicious intent. When auditing, consider the app’s legitimate functionality:
- Flashlight apps: Require
CAMERA(for flash control) and potentiallyACCESS_FINE_LOCATION(incorrectly, often for ad targeting) - Banking apps: Require
READ_PHONE_STATEfor device identification,CAMERAfor check deposits - Messaging apps: Require
READ_CONTACTSto find connections,RECORD_AUDIOfor voice messages - Fitness apps: Require
ACCESS_FINE_LOCATIONfor workout tracking
Be suspicious of permission combinations that exceed the app’s apparent function—a simple calculator requesting READ_CONTACTS or RECORD_AUDIO warrants investigation.
Best Practices for Permission Hygiene
Implement these practices to maintain tight permission control:
- Review before installing: Play Store’s permission summary shows all requested dangerous permissions before download
- Use “While Using” restrictions: Prefer “Allow only while using” over “Allow all the time” for location and camera
- Deny non-essential permissions: Many apps function without all requested permissions—test by denying
- Audit quarterly: Run comprehensive permission audits every three months
- Remove unused apps: Uninstall applications no longer in use rather than leaving them installed
- Check background access: Android’s Privacy Dashboard shows which apps accessed sensitive permissions recently
Conclusion
Regular Android app permission audits are a fundamental security practice. Whether using built-in tools for quick checks or implementing automated scripts for comprehensive reviews, staying aware of what access you’ve granted protects your personal data.
The Android permission system continues evolving—with each release offering users more control. Take advantage of these controls, audit regularly, and revoke permissions that no longer serve a purpose.
Related Reading
Built by theluckystrike — More at zovo.one