androidbroadcastreceiverintentfilterandroid-permissionsandroid-lint

How to fix Unprotected SMS BroadcastReceiver lint warning


My app needs to be able to receive SMS messages. It all works, but I get this lint warning:

BroadcastReceivers that declare an intent-filter for SMS_DELIVER or SMS_RECEIVED must ensure that the caller has the BROADCAST_SMS permission, otherwise it is possible for malicious actors to spoof intents.

How do I "ensure that the caller has the BROADCAST_SMS permission"?

In my manifest I have:

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application ...>
    <receiver
        android:name=".SmsReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter android:priority="1000">
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>
</application>

My code:

public class SmsReceiver extends BroadcastReceiver {
    public SmsReceiver() {}

    @Override
    public void onReceive(final Context context, final Intent intent) {

        final Bundle bundle = intent.getExtras();
        if (bundle != null) {
            final Object[] pdusObj = (Object[]) bundle.get("pdus");
            for (int i = 0; i < pdusObj.length; i++) {
                final SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                // use currentMessage
            }
        }
    }
}

Solution

  • Add android:permission="android.permission.BROADCAST_SMS" to the opening <receiver> tag. For example:

    <receiver
        android:name=".SmsReceiver"
        android:exported="true"
        android:permission="android.permission.BROADCAST_SMS">
    

    This android:permission attribute on a <receiver> specifies which permission the sender of the broadcast must hold in order for it to be able to broadcast to your <receiver>. It's a security measure; in this case, so you can be relatively certain that it is the system sending the SMS_RECEIVED broadcast. It's not strictly required, but lint will complain if it's not there, obviously.