Skip to content

Validate deep link args when resolving the start location#355

Merged
mbarta merged 1 commit into
mainfrom
mb/deeplink_args_vulnerability_fix
Jul 8, 2026
Merged

Validate deep link args when resolving the start location#355
mbarta merged 1 commit into
mainfrom
mb/deeplink_args_vulnerability_fix

Conversation

@mbarta

@mbarta mbarta commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

TurboSessionNavHostFragment.ensureDeeplinkStartLocationValid() validates the start location only inside the deepLinkExtras intent extra (android-support-nav:controller:deepLinkExtras).

AndroidX NavController also reads a second extra — deepLinkArgs (android-support-nav:controller:deepLinkArgs) — and merges it over deepLinkExtras when assembling each destination's arguments (arguments.putAll(globalArgs) followed by arguments.putAll(deepLinkArgs[index]), so the later write wins). Because an exported Activity's launch intent is externally controllable, a location (or any other argument) supplied via deepLinkArgs overrides the validated value and becomes the session's start destination — loading an unvalidated URL into the host's WebView.

This ports hotwired/hotwire-native-android#200 to turbo-android.

Fix

ensureDeeplinkStartLocationValid() now sanitizes the launching intent's deepLinkArgs in addition to validating deepLinkExtras:

  • each deepLinkArgs per-destination bundle is emptied so it can't override the validated start location;
  • a deepLinkExtras start location whose host doesn't match the configured start host is reverted to the configured start location, as before.

Sanitization applies to every launching intent. Intent-origin signals are too weak to gate on — callingPackage is only set for startActivityForResult launches, and Activity.referrer is backed by the attacker-settable EXTRA_REFERRER — so there is no reliable way to distinguish app-produced intents from external ones. Unconditional sanitization keeps legitimate same-host start locations working while preventing an external intent from steering the session to an arbitrary URL.

Tests

TurboSessionNavHostFragmentTest covers:

  • an off-host start location is reverted to the configured one;
  • a same-host start location is preserved;
  • deepLinkArgs are emptied so they can't override the validated start location.

🤖 Generated with Claude Code

NavController merges the deepLinkArgs intent extra over the validated
deepLinkExtras (last write wins), so an external Intent could override
the validated start location and load an arbitrary URL in the WebView.
Empty each deepLinkArgs bundle before validating the start location.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mbarta mbarta self-assigned this Jul 8, 2026
@mbarta
mbarta requested review from jayohms and jhutarek July 8, 2026 09:13
@mbarta
mbarta merged commit daceb0a into main Jul 8, 2026
1 check passed
@mbarta
mbarta deleted the mb/deeplink_args_vulnerability_fix branch July 8, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant