@@ -17,6 +17,7 @@ import dev.hotwire.turbo.views.TurboWebView
1717import kotlin.reflect.KClass
1818
1919internal const val DEEPLINK_EXTRAS_KEY = " android-support-nav:controller:deepLinkExtras"
20+ internal const val DEEPLINK_ARGS_KEY = " android-support-nav:controller:deepLinkArgs"
2021internal const val LOCATION_KEY = " location"
2122
2223abstract class TurboSessionNavHostFragment : NavHostFragment () {
@@ -114,22 +115,30 @@ abstract class TurboSessionNavHostFragment : NavHostFragment() {
114115 ? : throw IllegalStateException (" No current destination found in NavHostFragment" )
115116
116117 /* *
117- * Google's Navigation library automatically navigates to deep links provided in the
118- * Activity's Intent. This exposes a vulnerability for malicious Intents to open an arbitrary
119- * webpage outside of the app's domain, allowing javascript injection on the page. Ensure
120- * that deep link intents always match the app's domain.
118+ * Google's Navigation library automatically navigates to deep links provided in the launching
119+ * Intent, which lets a malicious Intent open an arbitrary page in the WebView. Sanitize the
120+ * Intent's attacker-controllable deep-link arguments so the start location stays within the
121+ * app's domain.
121122 */
122123 @VisibleForTesting
123124 internal fun ensureDeeplinkStartLocationValid (activity : FragmentActivity ) {
124- val extrasBundle = activity.intent.extras?.getBundle(DEEPLINK_EXTRAS_KEY ) ? : return
125+ val intent = activity.intent
126+
127+ // NavController merges deepLinkArgs over the validated deepLinkExtras (last write wins), so
128+ // empty each per-destination bundle to stop it overriding the validated start location.
129+ intent.extras?.getParcelableArrayList<Bundle >(DEEPLINK_ARGS_KEY )?.let { args ->
130+ intent.putParcelableArrayListExtra(DEEPLINK_ARGS_KEY , ArrayList (args.map { Bundle () }))
131+ }
132+
133+ val extrasBundle = intent.extras?.getBundle(DEEPLINK_EXTRAS_KEY ) ? : return
125134 val startLocationFromIntent = extrasBundle.getString(LOCATION_KEY ) ? : return
126135
127136 val deepLinkStartUri = startLocationFromIntent.toUri()
128137 val configStartUri = startLocation.toUri()
129138
130139 if (deepLinkStartUri.host != configStartUri.host) {
131140 extrasBundle.putString(LOCATION_KEY , startLocation)
132- activity. intent.putExtra(DEEPLINK_EXTRAS_KEY , extrasBundle)
141+ intent.putExtra(DEEPLINK_EXTRAS_KEY , extrasBundle)
133142 }
134143 }
135144
0 commit comments