Android App Security · Components & Intents · Lesson 3 of 5
Exported Components
Learn which parts of an app other apps can reach, and how developers lock the rest.
Open doors and locked doors
Every activity, service, receiver and provider in a manifest can carry one small attribute that matters a lot for security: android:exported.
exported="true"means other apps may start or talk to the component, for example by sending an explicit intent with its exact name.exported="false"means only the app itself (plus apps sharing its user ID and privileged system parts of Android) can reach it.
Think of the components as doors. The launcher needs to open the main screen, so that door must be exported. A share screen that accepts text from any app is exported on purpose too. But an internal settings screen, a sync service or a private database should be locked from the inside.
For years, the default was confusing. If a developer left the attribute out, the answer depended on the component type, whether it had an intent filter and which Android version it ran on. Content providers, for example, were exported by default on Android 4.1 and older. Developers sometimes exposed a component without ever deciding to.
Android 12 fixed part of this. If an app targets Android 12 or higher, every activity, service or receiver that has an intent filter must state android:exported explicitly. If it doesn't, the app can't be installed on Android 12 or later. Google's guidance now is simple: always set it, every time, so there's no guessing.
Remember one more rule from the docs. An intent filter isn't a lock. If only your own app should start a component, the safe move is no intent filter and exported="false", not a filter that seems obscure.
On the simulated phone, tap each component line in the QuickNotes manifest and sort them into exported and not exported.
Why open doors cause bugs
An exported component is a public entrance. Anything it does, any app on the phone can ask it to do, including a malicious app the user installed by mistake. That's why unprotected exported components show up again and again in security reports, and why bug bounty programs (where companies pay researchers to report flaws in their own apps) see so many of them.
Typical mistakes look like this:
- An exported activity meant only for internal use, like a debug or "reset account" screen, that skips the login check because the developer assumed only their own app would open it.
- An exported service that performs an action, like uploading files, for whoever asks.
- An exported content provider that returns private data, such as messages or tokens, to any app that queries it.
Google's own list of consequences includes leaked data, other apps changing how the app behaves, crashes on demand and even running code inside the vulnerable app.
Developers have several protections. The simplest is exported="false" for anything internal. When a component must be public but only for certain callers, the developer can require a permission with android:permission. A permission with the signature protection level is only granted to apps signed with the same key, which is the usual way for one company's apps to talk privately. Content providers also have separate readPermission and writePermission settings, and can hand out the temporary per-item grants you met in module 2 instead of opening everything.
If you build apps, check your own manifest the way a reviewer would. Search for every exported component, ask who should be able to call it, and treat everything it receives as untrusted input. Android Studio's lint checks also flag many risky settings.
Can you answer these?
- Which QuickNotes components can another app on the phone start or reach directly?
- A developer finds that their app's exported ResetPinActivity lets any caller set a new PIN. Only their own app ever needs to open it. What's the best fix?
Answer them in the app to earn 70 XP (Pro).
Answer in the app