Android deep link security vulnerabilities come down to two facts. First, a standard custom-scheme deep link is not verified, so any app on the device can register the same scheme and intercept the link, which lets a malicious app capture whatever the link carries, such as an auth token, and hijack the account. Second, the data inside a deep link is attacker-controlled input, so if your app trusts it without validation it can drive open redirects, WebView injection, or file access. The two mitigations are Android App Links, which bind an http link to a domain you own so no other app can claim it, and strict validation of every parameter a deep link delivers.
Short answer
The vulnerability is that unverified deep links are not exclusively yours and their contents are not trustworthy. Per Android's documentation, a standard deep link uses the intents system and is subject to the system disambiguation dialog because a custom scheme can be claimed by multiple apps, so a hostile app can register your scheme and receive the intent. Android App Links fix that by verifying http links against a Digital Asset Links file on your domain, so they open your app directly and cannot be claimed by another app. Beyond hijacking, treat every deep link parameter as untrusted input and validate it, since per OWASP inter-app communication and data received from other apps must be handled as untrusted.
What a deep link is, in plain terms
A deep link is a URI that opens a specific screen inside your app instead of just launching it, and Android routes it through the intents system. When your app declares an intent filter for a scheme or a host, the system knows that links matching it can be handled by your app, and tapping such a link either opens your app directly or offers it as a choice.
The mechanism that makes this convenient is the same one that creates the risk. Because routing is based on intent filters that any app can declare, the platform has to decide which app receives a link when more than one claims it. For an unverified custom scheme, that decision can involve a chooser dialog or, worse from a security view, silent delivery to whichever app is installed. So the routing that delivers your users to the right screen is also the routing an attacker can insert themselves into if the link is not bound to you.
App Links versus deep links
The core distinction the query asks about is verification, and it separates three things Android treats differently. A standard deep link, in Android's words, takes advantage of the intents system to route links to your app, is available on all Android versions, and is subject to the system disambiguation dialog because it is not verified. A web link is simply a deep link that uses the http or https scheme. An Android App Link is an enhanced deep link that verifies the link against your own website by establishing a trusted association between your app and your domain.
That trusted association is a Digital Asset Links file, assetlinks.json, hosted on your domain, and it is what changes the security picture. Per Android, once verified, App Links open the corresponding content in your app without requiring the user to select your app from a disambiguation dialog, and, critically, another app cannot claim a verified http link for a domain it does not control. App Links are supported on Android 6 and later on devices with Google services. So the practical rule is that deep links to your own website should use App Links, because verification is what makes the link exclusively yours.
Why unverified deep links are hijackable
An unverified custom-scheme deep link is hijackable because scheme ownership is not enforced, so more than one app can declare the same scheme and compete for the intent. If your app uses a custom scheme like myapp colon slash slash and a malicious app on the same device declares an intent filter for that scheme, the system may route the link to the attacker's app, either through a chooser the user misreads or silently. Whatever the link carries then lands in the attacker's hands.
This is exactly how deep links turn into account hijacking. A common pattern passes an OAuth authorization code or a session token back to the app through a custom-scheme redirect, and if a hostile app intercepts that redirect, it receives the code and can complete the sign-in as the victim. The spoofing works because the platform trusted the scheme claim rather than a verified identity. Binding the redirect to a verified App Link on a domain you control removes the ambiguity, because the attacker cannot register your domain, which is why sensitive redirects should never ride on an unverified custom scheme.
The second risk: unvalidated deep link input
Even a link that reaches the right app is dangerous if the app trusts its contents, because a deep link is a message from outside your trust boundary. Anyone can craft a URI with any path and any parameters and send it to your app, so the values inside are attacker-controlled. If your handler takes a parameter and loads it into a WebView, uses it as a file path, builds a database query from it, or treats it as an already-authenticated instruction, an attacker can supply a value that causes open redirection, script injection, path traversal, or unauthorized actions.
So the second class of deep link vulnerability has nothing to do with who receives the link and everything to do with what the app does with it. A link that opens a reset-password screen must still verify the token server-side rather than trusting a flag in the URI. A link that renders a URL in a WebView must confirm the URL is one you allow. The safe posture is to treat every deep link the way you would treat a form submitted by an anonymous stranger, because that is effectively what it is.
The three link types compared
The differences that matter for security are verification and exclusivity, which the table below lays out.
| Link type | Scheme | Verified? | assetlinks.json | Can another app claim it? |
|---|---|---|---|---|
| Deep link | Custom or http | No | Not used | Yes, via the same intent filter |
| Web link | http or https | No | Not used | Yes, shown in the chooser |
| Android App Link | http or https | Yes | Required on your domain | No, bound to your domain |
Read the last column as the security summary: only a verified App Link cannot be claimed by another app, which is why it is the right choice for any link that carries something sensitive.
Validation: handling deep links safely
Safe handling has two halves that map to the two risks, and both are needed. To stop hijacking, use App Links for links to your website so verification binds them to your domain, and never pass secrets such as tokens or authorization codes through an unverified custom scheme. To stop input abuse, validate every part of the incoming link before acting on it: check the path against an allowlist of screens, validate and sanitize each parameter, and confirm any URL you would open or render is one you permit.
The rule underneath both halves is that the deep link decides where to go, not whether the user is allowed to go there. Authentication and authorization still happen against your backend, using the session, not against a value in the URI. So a reset link carries a token you verify server-side, a screen route is matched against known routes rather than reflected blindly, and anything the link cannot prove remains untrusted. Handled this way, a deep link becomes a convenient pointer rather than a trusted command.
How to test your own deep links responsibly
On your own app and a device you control, you can confirm both risks without special tooling. Inspect your manifest for exported activities with intent filters on custom schemes, since those are the entry points, and use the Android debug bridge to fire a deep link at your app with crafted parameters, for example an unexpected path or a URL parameter, to see whether the handler validates it or acts on it blindly. A static analysis tool such as MobSF can list your intent filters and flag exported components for you.
To probe hijacking specifically, keep it to your own test devices and confirm whether a sensitive value travels through a custom scheme, because that is the token an interceptor would capture. The point of the exercise is to see where a link enters your app and what your code trusts about it, which is the boundary any responsible assessment stays within. If a crafted link changes behavior it should not, or a secret rides an unverified scheme, you have found the fix: verify the link and validate the input.
Remediation checklist
Working through these steps closes the common deep link gaps. The checklist below covers them.
| Step | Action | Done? |
|---|---|---|
| Verify your links | Use App Links with assetlinks.json for your domain | [ ] |
| Remove secrets from URIs | Stop passing tokens or codes over custom schemes | [ ] |
| Allowlist routes | Match incoming paths against known screens | [ ] |
| Validate parameters | Sanitize and check every value before use | [ ] |
| Enforce auth server-side | Verify tokens on the backend, not from the URI | [ ] |
| Audit intent filters | Confirm exported components expect untrusted input | [ ] |
The step teams skip most is the last one, since an exported activity with a deep link filter is the actual attack surface and is easy to overlook.
Where a scan fits
After you verify your links and validate their input, checking the whole app for the same pattern is worthwhile, because deep link handlers are rarely the only place untrusted input enters.
A scanner like PTKD.com analyzes your build and flags issues such as exported components that accept deep links without validation, secrets that could travel through them, and over-broad permissions by severity, mapped to OWASP MASVS. To be clear about the boundary: PTKD reports these findings for you to fix; it does not verify your App Links or rewrite your intent handlers. It points at the deep link entry points so you can bind and validate each one.
What to take away
- Standard custom-scheme deep links are not verified, so another app can claim the scheme and intercept the link, which is how deep links become account hijacking.
- Android App Links fix that by verifying http links against a Digital Asset Links file on your domain, so no other app can claim them and they open your app directly.
- Deep link parameters are attacker-controlled input, so validate every path and value and never let a URI stand in for authentication.
- Never pass tokens or authorization codes through an unverified custom scheme, and enforce auth server-side against the session.
- Test your own deep links with the debug bridge and a manifest review, and a tool like PTKD.com helps flag unvalidated deep link handlers app-wide.




