Implicitly Exported Android Component

ID

kotlin.android_exported_activity

Severity

high

Resource

Access Control

Language

Kotlin

Tags

CWE:926, OWASP-MASVS:MSTG-PLATFORM-1, OWASP:2021:A1, android

Description

Android components (activities, services, broadcast receivers) with intent filters are implicitly exported if the android:exported attribute is not explicitly declared. This exposes the component to other applications on the device, potentially allowing unauthorized access to sensitive functionality or data.

Rationale

Before Android 12 (API level 31), the system would allow this implicit behavior. From Android 12 onwards, apps targeting API 31+ must explicitly declare android:exported for components with intent filters, or installation will fail.

This detector identifies components that contain <intent-filter> elements but lack an explicit android:exported declaration.

Implicitly exported components create security vulnerabilities:

Vulnerable AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.vulnerable">

    <application>
        <!-- FLAW: Activity has intent filter but no android:exported -->
        <activity android:name=".SensitiveActivity">
            <intent-filter>
                <action android:name="com.example.SENSITIVE_ACTION" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <!-- FLAW: Service implicitly exported -->
        <service android:name=".PaymentService">
            <intent-filter>
                <action android:name="com.example.PROCESS_PAYMENT" />
            </intent-filter>
        </service>

        <!-- FLAW: Receiver accessible by any app -->
        <receiver android:name=".DataReceiver">
            <intent-filter>
                <action android:name="com.example.RECEIVE_DATA" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Without explicit android:exported="false", malicious applications can:

  • Launch the sensitive activity to access restricted functionality

  • Bind to the payment service to intercept or manipulate transactions

  • Send broadcasts to the receiver to inject malicious data

Remediation

Explicitly declare android:exported for all components with intent filters:

Fixed AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.secure">

    <application>
        <!-- FIXED: Explicitly exported for legitimate external access -->
        <activity
            android:name=".PublicActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="https" />
            </intent-filter>
        </activity>

        <!-- FIXED: Explicitly not exported for internal use only -->
        <activity
            android:name=".SensitiveActivity"
            android:exported="false">
            <intent-filter>
                <action android:name="com.example.INTERNAL_ACTION" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <!-- FIXED: Service not exported -->
        <service
            android:name=".PaymentService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.example.PROCESS_PAYMENT" />
            </intent-filter>
        </service>

        <!-- FIXED: Receiver not exported -->
        <receiver
            android:name=".DataReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="com.example.RECEIVE_DATA" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Best Practices

  1. Default to android:exported="false": Only export components when necessary for legitimate inter-app communication

  2. Use permissions for exported components: If a component must be exported, protect it with custom permissions:

    <activity
        android:name=".ProtectedActivity"
        android:exported="true"
        android:permission="com.example.permission.ACCESS_PROTECTED">
        <intent-filter>
            <action android:name="com.example.PROTECTED_ACTION" />
        </intent-filter>
    </activity>
  3. Validate input in exported components: Always validate data received from external intents

  4. Audit all components with intent filters: Review each component to determine if it should be accessible externally