From 4ca248708522528d17b5548d59c062506f5bac70 Mon Sep 17 00:00:00 2001 From: LeanBitLab <245915690+LeanBitLab@users.noreply.github.com> Date: Tue, 12 May 2026 18:23:27 +0000 Subject: [PATCH] Secure ACTION_VIEW web intents using CustomTabsIntent Replaced implicit `ACTION_VIEW` intents with `CustomTabsIntent` for HTTP/HTTPS web links in `MainActivity`. This mitigates intent hijacking risks where malicious apps could intercept generic view actions and expose user data or conduct phishing attacks. - Added `androidx.browser:browser:1.8.0` to `app/build.gradle.kts`. - Updated all relevant `Intent.ACTION_VIEW` usages targeting web URLs. - Retained `market://` links as standard intents, as they are intentionally meant for app stores. --- app/build.gradle.kts | 1 + .../java/com/leanbitlab/lwidget/MainActivity.kt | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9db95d8..d480e59 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -69,6 +69,7 @@ dependencies { implementation("androidx.core:core-ktx:1.15.0") implementation("androidx.appcompat:appcompat:1.7.0") implementation("com.google.android.material:material:1.12.0") + implementation("androidx.browser:browser:1.8.0") implementation("androidx.work:work-runtime-ktx:2.10.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") diff --git a/app/src/main/java/com/leanbitlab/lwidget/MainActivity.kt b/app/src/main/java/com/leanbitlab/lwidget/MainActivity.kt index 940fc69..0b6b125 100644 --- a/app/src/main/java/com/leanbitlab/lwidget/MainActivity.kt +++ b/app/src/main/java/com/leanbitlab/lwidget/MainActivity.kt @@ -22,6 +22,7 @@ import android.appwidget.AppWidgetManager import android.content.ComponentName import android.content.Context import android.content.Intent +import androidx.browser.customtabs.CustomTabsIntent import android.content.SharedPreferences import android.content.pm.PackageManager import android.os.Bundle @@ -121,13 +122,11 @@ class MainActivity : AppCompatActivity() { tvVersion.text = getString(R.string.changelog_version, versionName) findViewById(R.id.tv_github_link).setOnClickListener { - val intent = Intent(Intent.ACTION_VIEW, android.net.Uri.parse("https://github.com/LeanBitLab/Lwidget")) - startActivity(intent) + CustomTabsIntent.Builder().build().launchUrl(this@MainActivity, android.net.Uri.parse("https://github.com/LeanBitLab/Lwidget")) } findViewById(R.id.tv_privacy_policy).setOnClickListener { - val intent = Intent(Intent.ACTION_VIEW, android.net.Uri.parse("https://github.com/LeanBitLab/Lwidget/wiki/Privacy-Policy")) - startActivity(intent) + CustomTabsIntent.Builder().build().launchUrl(this@MainActivity, android.net.Uri.parse("https://github.com/LeanBitLab/Lwidget/wiki/Privacy-Policy")) } @@ -283,7 +282,7 @@ class MainActivity : AppCompatActivity() { startActivity(Intent(Intent.ACTION_VIEW, android.net.Uri.parse("market://details?id=org.breezyweather"))) } catch (e: Exception) { try { - startActivity(Intent(Intent.ACTION_VIEW, android.net.Uri.parse("https://f-droid.org/packages/org.breezyweather/"))) + CustomTabsIntent.Builder().build().launchUrl(this@MainActivity, android.net.Uri.parse("https://f-droid.org/packages/org.breezyweather/")) } catch (e2: Exception) {} } } else if (weatherMissing) { @@ -953,7 +952,7 @@ class MainActivity : AppCompatActivity() { com.google.android.material.snackbar.Snackbar.LENGTH_LONG ).setAction("Install") { try { - startActivity(Intent(Intent.ACTION_VIEW, android.net.Uri.parse("https://github.com/breezy-weather/breezy-weather/releases"))) + CustomTabsIntent.Builder().build().launchUrl(this@MainActivity, android.net.Uri.parse("https://github.com/breezy-weather/breezy-weather/releases")) } catch (e: Exception) {} }.show() return@setOnCheckedChangeListener @@ -1219,7 +1218,7 @@ class MainActivity : AppCompatActivity() { try { startActivity(Intent(Intent.ACTION_VIEW, android.net.Uri.parse("market://details?id=org.tasks"))) } catch (e: Exception) { - startActivity(Intent(Intent.ACTION_VIEW, android.net.Uri.parse("https://play.google.com/store/apps/details?id=org.tasks"))) + CustomTabsIntent.Builder().build().launchUrl(this@MainActivity, android.net.Uri.parse("https://play.google.com/store/apps/details?id=org.tasks")) } }.show() return@setOnCheckedChangeListener