๐Ÿ”— Part 7: Deep Link Hijacking in Flutterโ€Šโ€”โ€ŠHow Malicious Apps Can Launch Yours in Dangerous States

๐Ÿ”— Part 7: Deep Link Hijacking in Flutterโ€Šโ€”โ€ŠHow Malicious Apps Can Launch Yours in Dangerous States

FlutterPulse

This article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!๐Ÿš€

Deep links are a powerful feature in mobile apps. They let you open specific screens via a URIโ€Šโ€”โ€Šlike:

๐Ÿ”™ Check Previous Part [How Open Rules Can Expose All Your App's Data]

myapp://profile/123

Flutter makes it easy to implement deep linking with packages like uni_links, go_router, and platform-specific intent handlers.

But without strict validation, deep links can be hijacked or abused by malicious apps, rogue browsers, or crafted QR codes โ€” leading to:

  • Privilege escalation
  • Bypassing auth screens
  • Triggering unintended app behaviors
  • Exposing sensitive data or actions

๐Ÿšจ What's the Problem?

Flutter apps often handle deep links like this:

onGenerateRoute: (settings) {
final uri = Uri.parse(settings.name ?? '');
if (uri.pathSegments.first == 'profile') {
return MaterialPageRoute(
builder: (_) => ProfileScreen(userId: uri.pathSegments[1]),
);
}
...
}

If your app doesn't validate:

  • Who sent the link
  • Whether the user is authenticated
  • If the target screen should be accessible from an external source

...you open yourself to Deep Link Hijacking and Intent Injection.

๐Ÿ•ต๏ธโ€โ™‚๏ธ Real-World Exploit Scenarios

๐Ÿ’ฃ Exploit 1: Unauthorized Access to Privileged Screens

If the app allows:

myapp://admin/settings

...an attacker can craft a malicious app or browser to launch this intent:

adb shell am start -a android.intent.action.VIEW -d "myapp://admin/settings"

If your Flutter app doesn't check the user's role or login state before navigating โ€” the attacker gets admin access.

๐Ÿ’ฃ Exploit 2: URI Parameter Manipulation

URL like:

myapp://payment?amount=1000&recipient=attacker

...can be launched by:

  • Malicious apps
  • Spoofed SMS/WhatsApp/QR codes
  • Phishing sites

If your Flutter code doesn't sanitize or re-authenticate before processing the payment โ€” game over.

๐Ÿ’ฃ Exploit 3: App Spoofing

Attackers create apps with the same intent filter as yours:

<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="myapp"/>
</intent-filter>

Now when someone clicks a myapp:// link โ€” the malicious app intercepts it instead of yours.

๐Ÿ“‰ Real-World Impact

Risk Level: HIGH

๐Ÿ›ก๏ธ How to Fix It

Always perform backend or auth validation before opening deep-linked screens.

if (!isUserLoggedIn) {
redirectToLogin();
return;
}

if (uri.path == '/admin' && !userIsAdmin) {
showAccessDenied();
return;
}

โœ… Fix 2: Use Flutter Routing Libraries with Guard Support

Use libraries like go_router with auth checks:

GoRoute(
path: '/admin',
builder: (context, state) => const AdminScreen(),
redirect: (context, state) {
final isAdmin = context.read<Auth>().user?.isAdmin ?? false;
return isAdmin ? null : '/unauthorized';
},
),

โœ… Fix 3: Harden Android Intent Filters

Prevent app hijacking by setting explicit hosts and paths:

<data
android:scheme="https"
android:host="yourdomain.com"
android:pathPrefix="/app/" />

This ensures only links from your domain trigger the app โ€” not any rogue myapp:// intent.

โœ… Fix 4: Prompt for Reauthentication on Sensitive Flows

If a deep link opens sensitive flows (e.g., payments, account settings), require user reauthentication:

if (!await biometricAuthPassed()) {
return;
}
navigateToSecureScreen();

Track where deep links come from (intent origin, referrer) and log them server-side:

  • Who opened what?
  • Were they logged in?
  • Did the route match expected behavior?

โŒ Anti-Patterns to Avoid

โœ… Developer Checklist

  • Validate deep link target screens with auth + role
  • Never allow sensitive flows to be accessible via unauthenticated links
  • Use domain-bound intent filters (host=yourdomain.com)
  • Implement deep link routing with guards (go_router, auto_route)
  • Require biometric or PIN for sensitive deep link access
  • Monitor and log all deep link usage patterns

๐Ÿ‘€ Up Next

๐Ÿ”R Part 8: Runtime Code Injection โ€” How Attackers Hook Dart & Native Code to Tamper with Your Flutter App

Thank you for reading this article

If I missed something or made an error, please let me know in the comments. I'm always eager to learn and improve.

Give a clap ๐Ÿ‘ if you found this article helpful.

Report Page