Too Broad App Permissions
ID |
kotlin.android_too_broad_permissions |
Severity |
low |
Resource |
Access Control |
Language |
Kotlin |
Tags |
CWE:250, CWE:269, CWE:732, MASVS:MSTG-PLATFORM-1, OWASP:2021:M1, android, permissions |
Description
Android applications should follow the principle of least privilege by requesting only the minimum permissions necessary for their core functionality. Excessive permissions increase the attack surface, enable privacy violations, and may lead to app rejection from Google Play Store.
Rationale
Detecting excessive permissions helps prevent multiple security and privacy issues.
Execution with Unnecessary Privileges (CWE-250):
Applications requesting more permissions than needed create opportunities for:
-
Privilege escalation through compromised components
-
Increased impact of vulnerabilities (e.g., XSS with storage access becomes data theft)
-
Malware abuse of granted permissions
-
Unauthorized access to sensitive resources
Improper Privilege Management (CWE-269):
Permission mismanagement manifests in several patterns:
-
Critical permissions enabling malware capabilities (accessibility services, overlay windows)
-
Broad access permissions bypassing scoped security controls
-
Deprecated permissions when modern alternatives exist
-
Privacy-sensitive permissions without user-controlled alternatives
Google Play Policy Compliance:
Google Play Store enforces strict permission policies, rejecting apps that:
-
Request permissions unnecessary for core functionality
-
Use deprecated permissions on modern API levels
-
Access photos/videos without using Photo Picker API (enforced 2025)
-
Request SMS/Call Log permissions without being default handler apps
This detector identifies excessive permissions across four severity tiers:
-
TIER 1: Critical Permissions (Malware Indicators)
Dangerous permissions commonly abused by malware:
<!-- VULNERABLE: Accessibility service - 100% banking trojan usage -->
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
<!-- VULNERABLE: Overlay windows - 74% ransomware usage -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<!-- VULNERABLE: Device admin - prevents uninstallation -->
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN"/>
<!-- VULNERABLE: Silent app installation -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<!-- VULNERABLE: Usage tracking/surveillance -->
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
-
TIER 2: Broad Access Permissions
Permissions granting unrestricted system access:
<!-- VULNERABLE: All files access (bypasses scoped storage) -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<!-- VULNERABLE: Modify system settings -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!-- VULNERABLE: Modify secure system settings -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
-
TIER 3: Deprecated Permissions
Legacy permissions replaced by scoped alternatives:
<manifest>
<uses-sdk android:targetSdkVersion="33"/>
<!-- VULNERABLE: Deprecated on API 29+ -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- VULNERABLE: Deprecated on API 33+ -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- VULNERABLE: Deprecated on API 31+ -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- VULNERABLE: Deprecated on API 31+ -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
</manifest>
-
TIER 4: Privacy-Sensitive Permissions with Alternatives
Permissions where privacy-preserving APIs exist:
<!-- VULNERABLE: SMS access has permission-free alternative -->
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<!-- VULNERABLE: Location - consider coarse instead of fine -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- VULNERABLE: Contacts - picker API available -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!-- VULNERABLE: Camera - request at runtime only -->
<uses-permission android:name="android.permission.CAMERA"/>
Research on Android malware families shows specific permission patterns. For example, banking trojans often use accessibility permissions:
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
<uses-permission android:name="android.permission.READ_SMS"/> <!-- OTP interception -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <!-- Phishing overlays -->
On the other hand, ransomware use overlay windows along with device admin:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN"/>
Stalkerware / Spyware often combine permissions for exfiltrating sensitive information:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Remediation
-
Remove Unnecessary Permissions
Audit all requested permissions and remove those not essential to core functionality:
<!-- DON'T: Excessive permissions for a photo sharing app --> <uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!-- DO: Minimal permissions with modern APIs --> <!-- Use Photo Picker API - no permission required --> <!-- Use CameraX with runtime permission request --> <!-- Location only if core feature, prefer COARSE --> -
Migrate to Modern APIs
-
Storage Access (API 29+):
// DON'T: Deprecated broad storage access <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> // DO: Use Scoped Storage and Photo Picker ActivityResultLauncher<PickVisualMediaRequest> pickMedia = registerForActivityResult(new PickVisualMedia(), uri -> { // Handle selected photo (no permission required) }); pickMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageOnly.INSTANCE) .build()); -
SMS/OTP Verification:
// DON'T: Request SMS permissions <uses-permission android:name="android.permission.READ_SMS"/> // DO: Use SMS Retriever API (no permissions) SmsRetrieverClient client = SmsRetriever.getClient(context); client.startSmsRetriever(); -
Bluetooth (API 31+):
<!-- DON'T: Deprecated permissions --> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <!-- DO: Use new granular permissions --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/> -
Contacts Access:
// DON'T: Request full contacts access <uses-permission android:name="android.permission.READ_CONTACTS"/> // DO: Use Contacts Picker (user selects specific contacts) ActivityResultLauncher<Void> pickContact = registerForActivityResult(new PickContact(), uri -> { // Handle selected contact (no permission required) }); pickContact.launch(null);
-
-
Runtime Permission Requests
For necessary permissions, request at runtime with clear justification:
// Request permission only when needed with rationale if (ContextCompat.checkSelfPermission(this, CAMERA) != PERMISSION_GRANTED) { if (shouldShowRequestPermissionRationale(CAMERA)) { // Show explanation dialog showCameraRationaleDialog(() -> { requestPermissions(new String[]{CAMERA}, REQUEST_CAMERA); }); } else { requestPermissions(new String[]{CAMERA}, REQUEST_CAMERA); } }
The following table shows alternative approaches by permission:
| Permission | Modern Alternative |
|---|---|
READ_EXTERNAL_STORAGE |
Photo Picker API, Scoped Storage (MediaStore), Storage Access Framework (SAF) |
WRITE_EXTERNAL_STORAGE |
Scoped Storage with MediaStore, getExternalFilesDir() for app-specific storage |
READ_SMS / RECEIVE_SMS |
SMS Retriever API (OTP), SMS User Consent API (user approves specific message) |
ACCESS_FINE_LOCATION |
ACCESS_COARSE_LOCATION (sufficient for most use cases like weather, timezone) |
READ_CONTACTS |
Contacts Picker API (user selects specific contacts, no permission needed) |
CAMERA |
Request at runtime only when camera feature is used, not upfront |
BLUETOOTH / BLUETOOTH_ADMIN |
BLUETOOTH_CONNECT, BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE (API 31+) |
READ_PHONE_STATE |
READ_PHONE_NUMBERS (API 31+) for specific access, or remove if not needed |
Configuration
This detector provides configuration properties to customize permission lists for specific app contexts:
properties:
# TIER 1: Critical permissions (malware indicators)
criticalPermissions:
- android.permission.BIND_ACCESSIBILITY_SERVICE
- android.permission.SYSTEM_ALERT_WINDOW
# Add custom critical permissions
# TIER 2: Broad access permissions
broadAccessPermissions:
- android.permission.MANAGE_EXTERNAL_STORAGE
# Add custom broad permissions
# TIER 3: Deprecated permissions
deprecatedPermissions:
- android.permission.WRITE_EXTERNAL_STORAGE
# Add custom deprecated permissions
# TIER 4: Privacy-sensitive permissions
privacySensitivePermissions:
- android.permission.READ_SMS
# Add custom privacy-sensitive permissions
References
-
Android Developer: Permissions Overview and Permissions Reference.
-
Android Developer: Photo Picker API
-
Android Developer: Data and File Storage
-
OWASP MASTG-TEST-0024: Testing for App Permissions
-
Google Play: Permissions Policy
-
Google Play: Photo/Video Permissions 2025 Update
-
CWE-250: Execution with Unnecessary Privileges
-
CWE-269: Improper Privilege Management
-
CWE-732: Incorrect Permission Assignment for Critical Resource