Custom URL schemes like myapp:// are a convenient way to open your app from a link, and a weak foundation to build security on. The problem is that iOS does not guarantee a scheme is unique, so another app, including a malicious one, can register the same scheme and intercept the URLs meant for you. If those URLs carry anything sensitive, an OAuth callback, a token, a reset link, that is a hijacking risk. The fix is Universal Links, which are tied to a domain you control. Here is how scheme hijacking works and how to handle deep links securely.
Short answer
A custom URL scheme like myapp:// can be hijacked because iOS does not enforce uniqueness, so another app can register the same scheme and receive URLs intended for your app. Per Apple's guidance, this makes custom schemes unsuitable for anything sensitive, since a malicious app could intercept data passed in the URL, such as an OAuth callback or a token. The secure alternative is Universal Links, which are bound to a domain you verify with an apple-app-site-association file, so they cannot be claimed by another app. Use Universal Links for sensitive links, never pass secrets through a custom scheme, and treat incoming URLs as untrusted input.
What you should know
- Custom schemes are not unique: iOS does not stop another app registering yours.
- They can be hijacked: a malicious app can intercept your scheme's URLs.
- Do not pass secrets via custom schemes: tokens and callbacks can be intercepted.
- Universal Links are domain-bound: tied to a domain you verify, so they cannot be claimed.
- Treat incoming URLs as untrusted: validate whatever arrives.
What is URL scheme hijacking?
It is another app registering your custom scheme and receiving links meant for you. On iOS, when you define a custom URL scheme, any other app can declare the same one, and if more than one app registers a scheme, the system does not guarantee which one handles it. A malicious app can deliberately register a popular app's scheme to intercept the URLs sent to it. That matters when those URLs carry sensitive data: a classic case is an OAuth flow that returns the authorization response to myapp://callback, where a hijacking app registered to that scheme could receive the response and the tokens in it. So scheme hijacking turns a convenient deep-link mechanism into an interception path whenever sensitive information rides on the URL.
Custom schemes versus Universal Links
The difference is whether the link is bound to something you control. The table compares them.
| Aspect | Custom URL scheme | Universal Link |
|---|---|---|
| Uniqueness | Not guaranteed; any app can register it | Bound to your verified domain |
| Hijack risk | Yes, another app can intercept | No, it cannot be claimed by another app |
| Setup | Declare the scheme in Info.plist | Host an apple-app-site-association file on your domain |
| Fit for sensitive data | No | Yes, when needed |
| Fallback | None if the app is absent | Opens your website if the app is not installed |
Universal Links use a URL on a domain you own, verified by hosting an apple-app-site-association file, so only your app, associated with that domain, handles them. That binding to a domain you control is exactly what custom schemes lack, which is why Universal Links are the right choice for any link that matters.
How do you handle deep links securely?
Prefer Universal Links, keep secrets off the URL, and validate input. For any link that carries sensitive meaning, use Universal Links bound to your verified domain rather than a custom scheme, so it cannot be hijacked. For authentication specifically, use the system's secure authentication session for OAuth rather than returning tokens to a custom scheme, since that flow is designed to deliver the result to your app safely. Never pass secrets, tokens, or trusted commands through a custom scheme, and treat every incoming URL, of any kind, as untrusted input: validate it, do not assume it came from a legitimate source, and do not perform a sensitive action just because a URL asked. The principle is that a deep link can be forged or intercepted, so it should trigger only safe behavior unless the link type itself, like a Universal Link, provides the trust.
What to watch out for
The first trap is running an OAuth or sensitive callback through a custom scheme, where a hijacking app can intercept the token; use Universal Links or the secure authentication session. The second is trusting an incoming custom-scheme URL as if it authenticated the caller, when anyone can craft one. The third is assuming your scheme is yours, when iOS does not guarantee it. A pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled IPA against OWASP MASVS and surfaces the URL schemes your app declares and how it handles links, so you can spot a sensitive flow riding on a custom scheme before you ship. Moving sensitive links to Universal Links is the fix.
What to take away
- A custom URL scheme can be hijacked because iOS does not guarantee uniqueness, so another app can register it and intercept your links.
- Never pass secrets, tokens, or OAuth callbacks through a custom scheme, since a hijacking app could intercept them.
- Use Universal Links, bound to a domain you verify, for any link that matters, and the secure authentication session for OAuth.
- Treat all incoming URLs as untrusted input, and use a pre-submission scan such as PTKD.com to find sensitive flows riding on custom schemes.



