Kotlin has become a language of choice for modern Android development, and its popularity among backend developers is also increasing. As Kotlin's use grows, so does the demand for specialized security tools. That's why we at Sonar have enhanced our powerful static analysis engine to provide advanced security scanning for Kotlin code.
In this blog post, we'll demonstrate our new Kotlin security analysis features by walking you through two real-world vulnerabilities uncovered by SonarQube Cloud. First, we'll look at a security misconfiguration in the Read You Android app that allows attackers to intercept encrypted communications. Then, we'll explore a more intricate Path Traversal taint flaw in the receive_sharing_intent package, which shows the security challenges of inter-app communication on Android. For each flaw, we'll break down the technical details, explain how an attacker could exploit them, and discuss the recommended patches
Read You: Trusting all certificates
Read You is an open-source RSS reader for Android with over 6000 stars on GitHub. It periodically fetches RSS feed content from the user-configured URLs, for which it uses the popular OkHttp library. When scanning Read You's code base with SonarQube, an issue was raised about the usage of TLS:
View the issue on SonarQube Cloud

When establishing a secure HTTPS connection, an application must validate the web server's TLS certificate to cryptographically ensure it is communicating with the correct server. This verification logic is built into the OkHttp library and is safe by default, but Read You modifies it by implementing its own, non-validating trust manager when the trustAllCerts
parameter is set to true
.
The parameter defaults to true
, so we had to further investigate the source code to see if it is ever set to a different value. The code from the issue is inside the setupSsl()
function, and this function is only called from the cachingHttpClient()
function:
app/src/main/java/me/ash/reader/infrastructure/di/OkHttpClientModule.kt:
fun cachingHttpClient(
// ...
trustAllCerts: Boolean = true,
// ...
): OkHttpClient {
// ...
if (!clientCertificateAlias.isNullOrBlank() || trustAllCerts) {
builder.setupSsl(context, clientCertificateAlias, trustAllCerts)
}
return builder.build()
}
Here, the value passed to the trustAllCerts
parameter comes from a parameter with the same name. This parameter also defaults to true
, and its value is not overridden when cachingHttpClient()
is called:
app/src/main/java/me/ash/reader/infrastructure/rss/provider/ProviderAPI.kt:
abstract class ProviderAPI(context: Context, clientCertificateAlias: String?) {
protected val client: OkHttpClient = cachingHttpClient(
context = context,
clientCertificateAlias = clientCertificateAlias,
)
.newBuilder()
.addNetworkInterceptor(UserAgentInterceptor)
.build()
// ...
}
This means that certificate verification is never enabled in Read You, allowing all communication to be intercepted by a Man-in-the-Middle (MitM) attacker!
An attacker can exploit this by positioning themselves as a Man-in-the-Middle (MitM) between the victim's device and the internet. A common scenario for this is setting up a malicious Wi-Fi access point that looks like a free Wi-Fi offering in a public place.
Because the Read You app does not validate TLS certificates, the attacker can present a self-signed certificate, intercept the connection, and then read or modify all data exchanged between the app and the server. This allows the attacker to see which articles the user is reading, modify the content of those articles to show fake information, or even steal credentials if the user connects to a password-protected RSS feed.
Patch
To fix such a vulnerability, always use the default trust manager provided by the platform, which correctly performs certificate and hostname validation. A feature to allow self-signed certificates for specific feeds should be an explicit user choice, with clear warnings about the risks involved. Unfortunately, we were not able to reach the maintainer of Read You, so the vulnerability remains unfixed. We therefore chose to publish about it so that users can make an informed decision whether or not they want to continue using the app.
receive_sharing_intent: When sharing becomes insecure
receive_sharing_intent is a popular Flutter plugin that allows an application to receive data shared from other apps via Android's Intent system. Flutter, being a cross-platform framework, requires apps and libraries to implement platform-specific logic in the respective native languages. For Android, this includes Kotlin, so the receive_sharing_intent plugin implemented the Intent handling there.
Android Intents and ContentProviders
Android uses so-called Intents for inter-process communication. An app can send an Intent to request an action from another app, such as sharing a file. Intents can contain small amounts of data, but if two apps want to exchange larger amounts of data, they should use a different Android mechanism.
The app that wants to share the data will create and send a content://
URI to the receiving app. This URI points to a ContentProvider
, which is a component that manages access to a structured set of data. When the receiving app gets the URI, it uses a ContentResolver
to request the data (e.g., the file's content and its display name) from the ContentProvider
of the sending app. Any app on the device can expose a ContentProvider
, and the data it returns is entirely under its control.

Path traversal via the display name
Coming back to the receive_sharing_intent plugin, we can see that SonarQube raises a Path Traversal vulnerability in its Kotlin code:
View the issue on SonarQube Cloud

In line 99, the plugin requests files from a different app based on the content://
URI it received through an Intent. This returns a cursor that can be used to access multiple files, as well as certain metadata fields per file. One of these fields is the file's display name, accessible through the _display_name
column.
This display name is then used to construct a file path in line 104, saved as a File
object in the targetFile
variable. Later in lines 123-127, this file path is used to write the file's content to disk. However, there is no verification of the display name! This allows an attacker to insert a Path Traversal sequence (../
) into the display name, leading to a controlled file write. But how could an attacker even control this?
Android threat model: malicious apps
On Android, apps are much more restricted than applications on a common desktop OS. Permissions guard what an app can do, and most apps only have a restricted set of permissions that are granted by default. Apps that want to perform privileged actions, such as accessing user files, using the camera, or activating the microphone, need to get approval from the user.
To make this permission system work, Android also isolates individual apps from each other. If any app could coerce an app holding a privileged permission to perform actions on its behalf, then the permission would be circumvented. Therefore, apps should not trust other apps and view them as potentially malicious. This might seem overly cautious, but there have been numerous instances of malicious apps installed by millions of users, oftentimes even distributed via the Google Play Store.
In the case of the receive_sharing_intent plugin, any app using it would be vulnerable to the path traversal file write. If a malicious app is installed, it can craft a special Intent containing a content:// URI pointing to its own malicious ContentProvider. When the receive_sharing_intent plugin queries this provider, the malicious provider can respond with a filename containing a path traversal sequence, such as ../settings.xml:

The final impact depends on the specific app. On Android, path traversal vulnerabilities usually have less impact compared to classic server applications. There are more restrictions regarding where an app can write, and most of the file system is read-only for an app. This makes it harder for attackers to increase their impact, but it can still be possible depending on the app at hand.
Patch
As recommended by Android's security documentation, an application should never trust the filename provided by a ContentProvider
. The correct approach is to ignore the provided name and instead create a file with a randomly generated name within the intended cache directory:
val uuid = UUID.randomUUID().toString()
val targetDirectory = new File(context.cacheDir, uuid)
targetDirectory.mkdir()
targetFile = File.createTempFile("share", null, targetDirectory)
Timeline
Date | Action |
2024-11-21 | We report the receive_sharing_intent vulnerability to the maintainer via email |
2024-12-09 | We ask the receive_sharing_intent maintainer for an update |
2025-02-15 | We report the Read You vulnerability via a GitHub Security Advisory |
2025-03-10 | We ping the Read You maintainer in the GitHub Security Advisory |
2025-05-19 | We remind the Read You maintainer that our 90-day disclosure deadline has elapsed |
Summary
The vulnerabilities in Read You and receive_sharing_intent demonstrate some of the security challenges present in Kotlin Android apps. From misconfigurations like disabled TLS validation to more complex flaws in inter-app communication, developers face a significant challenge in securing their code.
These findings underscore the importance of automated security analysis. SonarQube's new, advanced Kotlin scanning capabilities are designed to be a developer's first line of defense, automatically detecting a wide range of security hotspots and vulnerabilities directly in the development lifecycle. By integrating static analysis early and often, development teams can catch and fix critical security issues before they ever reach production, securing their applications and protecting their users.
Visit this page for more guidance on how Sonar can help you build quality mobile apps. You can download a free version of SonarQube here.
Related Blog Posts
- New Spring framework rules in SonarQube
- The Power of Taint Analysis: Uncovering Critical Code Vulnerability in OpenAPI Generator
- Code Interoperability: The Hazards of Technological Variety
- Excessive Expansion: Uncovering Critical Security Vulnerabilities in Jenkins
- Apache Dubbo Consumer Risks: The Road Not Taken