TL;DR
- Activities are the main way Android apps interact with users
- They expose a small attack surface but still need testing during assessments
- Exported activities can be launched out of order and abused by other apps
- Hidden or debug activities often remain in production builds and should be removed
- Missing FLAG_SECURE allows screenshots and screen recordings of sensitive data
- WebViews can expose JavaScript, debugging and cached data if not configured securely
Introduction
Android splits its communications into multiple components, some of which we’ve written about before. One of these components is Activities, which are generic components that run in a foreground thread and interact directly with the user.
Is this a fancy way of saying windows?
You got me. Yes, it’s a fancy way of saying a window, but not quite. By definition, it’s something that the user performs an activity with, whether this be checking their bank balance, playing a game or typing a message.
And, yes, hypothetical person that I’m talking to, that does mean it lives in a window. The window often takes up the full screen, but doesn’t have to. It can be composed of multiple different components built by the framework du jour (as it has a habit of changing on a regular basis, just to really annoy anybody developing Android apps).
Currently, the mechanism for creating windows is Jetpack Compose, which manages this process using the @Composable annotation. This can be quite confusing for those who are not familiar with it. The windows components are all the ones that have existed for a while, including elements such as tables, lists and snackbars (a more flexible toast; it’s called a toast because it pops up, UX designers, what are they like??).
Interaction
Like anything in Android, activities can be exported and can be communicated with by sending an intent. They are usually defined in the manifest, with one primary activity, conventionally called MainActivity.
For an activity to be interfaced with, it needs to be exported, using the android:exported attribute or if it has an intent-filter, just like a broadcast receiver.

Just like a broadcast receiver, we can send it an intent to communicate with the activity, e.g. to start that activity we can send an intent using the am command (activity manager).
am start -a android.settings.EDIT_EMERGENCY_INFO -c android.intent.category.DEFAULT -n com.android.emergency/.edit.EditInfoActivity
I’m not going to go into intents, just yet, but you can see the rough pattern showing the action and category defined in the manifest, along with the intent destination (signified by -n) which is the app and activity names.
The dumpsys command dumps data out of running services, including ActivityManager, using the activity sub command. This is useful for enumerating how an app’s activities are seen by the system. For example, to dump all of a package’s active activities, which will, amongst other things, show details on the activity’s views (UX components) and application details.
dumpsys activity -p com.android.emergency activities

Security concerns
Activities are maybe the least likely of Android components to have security concerns, but there are a few things that have been found in the past that could have an impact. This is not exhaustive.
Hidden activities
We occasionally see “hidden” activities, where there’s no route, or a complex route of secret touches to get to. This can often allow access to secret configuration screens or debugging access (e.g. there are many engineering apps out there).
Sometimes there’s a system app which can’t normally be launched unless you identify the activity and launch it separately.
Simply put: don’t do this. “Secret” codes are easy to reverse engineer and hidden screens don’t remain hidden. If you have debug screens in your app, remove them when you build the production version of the app.
Secure windows
By default, the displayed window can be accessed by the system. This is used to take a screenshot using the volume down + power key combination. It is also used by the Recents Screen (also called the Overview screen) which shows a scaled screenshot of all activities. This screen can be accessed by a drag up from the bottom, or by using the Recents button, if you prefer the old-style taskbar.
Other opportunities to copy the screen are used when casting or recording the screen through multiple different techniques. For example, I often use the scrcpy program, which connects through adb to allow me to control my testing device from my Windows laptop.
It’s not always desirable to show the contents of an activity, if you have sensitive information, e.g. PII, a password or a credit card number on screen, then this shouldn’t really be screenshotted.
Fortunately there’s a technical solution, there’s a layout flag, FLAG_SECURE that can be applied to a window which states that the window can only be shown on secure displays (i.e. ones that also have SECURE flag).
This is relatively simple to apply when creating the window, for example I wrote a trivial app that hides the window, just adding the following statement in the onCreate() method before I created its views:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
When any attempt to take a screen capture is made, the whole window is just set to white, making it generally private.

Think about both the user experience (UX) and the privacy needs of your app. Using FLAG_SECURE can make things less convenient, as anyone who has tried to copy card details from one app to another will know, but it does stop screenshots, screen recordings and previews from exposing sensitive data. It’s a trade-off between usability and protection, and one worth considering carefully.
Normally we won’t raise this as a finding unless the app and data come under regulations, such as PCI-DSS.
WebViews
A WebView is a specialised UX component that allows HTML content to be rendered within an app. This can often be used to make an app quickly by just placing loading an existing web site in the app.
This is one of my biggest bugbears with mobile app development: if your app just uses your website, maybe consider not making an app, just tune your website for mobile use and let people use the website. That will reduce costs and the attack surface, resulting in a better UX for users. Especially do not put banners on your website to hint that people download an app which just runs the website in a WebView. Reddit, I’m looking at you here.
WebViews run in a cut-down Chromium instance which is controllable from the app, even allowing JavaScript within the WebView to access an object within the app. This means that they can be vulnerable to all normal web vulnerabilities, although the impact can change, e.g. from a real-world test: an XSS can now launch your phone’s dialler with a number all set and ready to call.
There are options to WebViews which can also be considered, some of these are web oriented, such as WebSettings.MIXED_CONTENT_NEVER_ALLOW which tells the WebView how to handle content from an insecure origin.
There is also WebSettings.setJavaScriptEnabled(boolean) which defaults to False and stops JavaScript being run in a WebView, although this is a great idea from a security perspective, it reduces the flexibility of many WebViews.
WebViews, like web browsers also cache data, which is stored in the app’s sandbox. There is a potential to cache data, like card details that may not be desirable. Cache hints can be used through HTTP headers, like those of a web browser. The cache can be disabled, but this often does not produce a desired UX path.
One of the most often missed method calls is WebView.setWebContentsDebuggingEnabled() which allows the state of the WebView to be inspected and modified through adb. The Chrome browser has a built-in interface to mirror the screen of remote WebViews and use developer tools through that.

Using Chrome for a task
Related to the WebView above, this is something I’ve seen in a couple of apps, where the app used a Chrome instance to connect to the authentication provider and return a token.
Mobile Chrome has remote debugging enabled. This means that it is possible to use remote debugging and catch the data as it passes through, or replay requests as if it came from the mobile device.
Don’t do this. If you have to shell out to a web page, use a WebView, you have more control over its parameters and what it allows.
Conclusion
Activities are the components are most likely to interact with, but provide the least attack surface for the application.
Ensure that activities are as restricted as needed and can’t be started out of sequence by other apps. Use permissions or intent-filters where needed.
Ensure that debugging features such as hidden activities and WebView debugging are removed when the production version of the app is written.
If the activity contains sensitive information, consider blanking it for the lifetime of that information being visible.
Be careful about spawning other apps to perform apps, such as authentication.