VNX-926: Android component exported with no permission protecting it
Reports an <activity>, <activity-alias>, <service>, <receiver> or <provider> in AndroidManifest.xml that declares android:exported="true" and no android:permission (a provider without android:permission needs both android:readPermission and android:writePermission; with only one, its other side is open and it is reported): any app on the device can start, bind, broadcast to or query it (CWE-926). The finding is on the android:exported line, and the start tag may span several lines. Not reported: the launcher activity (an intent-filter with category LAUNCHER or LEANBACK_LAUNCHER, which must be exported), components that are not exported or protected by a permission, components of an <application> that declares android:permission (the default for every component), components the manifest merger removes (tools:node="remove"), commented-out elements (single-line or inside a multi-line comment), and XML files other than AndroidManifest.xml. Components exported implicitly by an intent-filter on old target SDKs are not reported, because the target SDK is not known from the manifest line.
| Field | Value |
|---|---|
| Rule ID | VNX-926 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Any file |
| CWE | CWE-926 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | improper-export-android android cwe-926 |
| Source | internal/sast/rules/vnx-926.rego |
Overview
Reports an
Why This Matters
An exported component is an entry point any other app on the device can call. With no permission on it, a malicious app can start the activity with crafted extras, bind to the service, send forged broadcasts to the receiver or read and write the provider’s data, using the component’s own privileges.
What Gets Flagged
<service android:name=".PlaybackService" android:exported="true"/>
<provider
android:name=".NotesProvider"
android:authorities="com.example.notes"
android:exported="true" />
What Is Not Flagged
<!-- launcher activity: must be exported -->
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".SyncService"
android:exported="true"
android:permission="com.example.permission.SYNC" />
Remediation
- Set
android:exported="false"on every component that only your own app uses. - When another app must reach the component, protect it with
android:permissionnaming asignature-level permission you declare. - For a provider, use
android:readPermission/android:writePermissionorandroid:grantUriPermissionswith per-URI grants. - For a confirmed false positive, add a
vulnetix-ignore: VNX-926comment on the line.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-926
// nosec vnx-926
Or record an ignore rule: vulnetix ignore add --rule vnx-926 --reason "...". See Suppressing findings.