This content originally appeared on Level Up Coding - Medium and was authored by Raúl Ferrer
The Hidden Dangers of Custom URL Schemes.

As developers, we often use custom URL schemes (e.g., myapp://) to handle deep linking in our iOS apps. These schemes allow the user to freely navigate specifically to a subpart of an application by clicking a link, and thus they can allow content sharing, and provide a very fluid experience.
But here’s the catch:
Custom URL schemes could expose your app to security vulnerabilities.
Let’s check how these schemes can be exploited and why you should consider switching to Universal Links instead.
What is a custom URL scheme?
Custom URL schemes are special URL patterns that your app listens for. For example, when we create a custom scheme like myapp://, our app can respond when the system encounters a link with that scheme.
Through this, deep linking to particular sections of your app (e.g., opening a specific page or triggering an action) is possible.
We can relatively easily implement custom URL schemes, and there are some use cases, particularly for internal communication between applications within a controlled ecosystem, that make them very attractive. However, these public-facing deep links present significant security risks.
How does the custom URL scheme attack work?
OK, so we know we can put a custom URL scheme in our app, but any other app can register the same custom URL scheme.
That means that if a malicious app registers the same custom scheme as ours, myapp://, it can intercept deep links intended for our app, redirecting users to harmful content, stealing sensitive information, or even hijacking the app’s functionality.
Let’s look at an example:
- A user clicks on a link, myapp://checkout, thinking it will open our app’s payment page.
- Instead, a malicious app that also registered the same scheme intercepts the link and takes over.
- The user can then be redirected to a phishing page or tricked into installing malware, all because our app’s custom scheme was vulnerable.
Why custom URL schemes are risky
Custom URL schemes look easy and easy to put into practice, however, they have severe risks:.
- Hijacking. If any other application can hijack your scheme, there will be malicious redirection.
- No verification. Compared to Universal Links, custom URL schemes do not require the domain verification, and this makes it impossible to verify that your app is also the one which would process the link.
- Security vulnerabilities. Such vulnerabilities can offer attackers opportunities for phishing users, extracting data or allowing unwanted access to your app.
The solution: Universal Links
Apple introduced Universal Links to address these security flaws. Unlike custom URL schemes, Universal Links are associated with a validated web domain and only your app is able to process the links that go to your domain.
Here’s why they’re a much safer choice:
- App ownership verification. By the means of Universal Links, you have to register your domain with Apple in order to be verified as the owner of the same. This verification prevents other apps from hijacking your links.
- No risk of hijacking. Since Universal Links are directly associated with your domain, and a bad application cannot get them. Only your app will be able to access these links, and thus, will continue to safeguard your users from being redirected to malicious sites/URLs.
- Fallback to web. If the user does not have your app installed, the URL will load in Safari, but continue to deliver access to your content via your own solution though without the security problems from a nonstandard scheme.
Technical implementation requirements
Ok. Let’s implement Universal Links. At this point we’ll need:
- An apple-app-site-association (AASA) file hosted on your HTTPS server at a specific location
- Proper app configuration in Xcode, including entitlements and associated domains
- Support for both HTTP and HTTPS URLs in your implementation
Here’s how to implement both approaches:
Custom URL scheme Implementation
1. First, register your URL scheme in Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
<key>CFBundleURLName</key>
<string>com.example.myapp</string>
</dict>
</array>
2. Handle the custom URL scheme in your SceneDelegate:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
// Handle myapp:// URLs
if url.scheme == "myapp" {
let path = url.host
let parameters = url.queryParameters
// Example: myapp://products?id=123
if path == "products" {
if let productId = parameters["id"] {
navigateToProduct(id: productId)
}
}
}
}
// Helper extension to parse URL parameters
extension URL {
var queryParameters: [String: String] {
var params: [String: String] = [:]
guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems else { return params }
for item in queryItems {
params[item.name] = item.value
}
return params
}
}Universal Links Implementation
- Create an apple-app-site-association file (hosted at yourdomain.com/.well-known/apple-app-site-association):
{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAM_ID.com.example.myapp",
"paths": [
"/products/*",
"/profile/*",
"NOT /api/*"
]
}]
}
}2. Add Associated Domains capability in Xcode and specify your domain:
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:yourdomain.com</string>
</array>
3. Handle Universal Links in your SceneDelegate:
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else {
return
}
// Handle Universal Links
let pathComponents = url.pathComponents
// Example: https://yourdomain.com/products/123
if pathComponents.count >= 2 && pathComponents[1] == "products" {
if pathComponents.count >= 3 {
let productId = pathComponents[2]
navigateToProduct(id: productId)
}
}
}
// Helper function to handle navigation
private func navigateToProduct(id: String) {
// Navigate to the product detail view
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first,
let rootVC = window.rootViewController as? UINavigationController else {
return
}
let productVC = ProductDetailViewController(productId: id)
rootVC.pushViewController(productVC, animated: true)
}4. Test Universal Links with the following commands:
# Create and sign the apple-app-site-association file
cat > apple-app-site-association << EOF
{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAM_ID.com.example.myapp",
"paths": ["/products/*"]
}]
}
}
EOF
# Validate the file (requires aasa-validator npm package)
npx aasa-validator apple-app-site-association
# Test the link on device
xcrun simctl openurl booted "https://yourdomain.com/products/123"
Benefits of switching to Universal Links
- Increased security. Universal Links are not vulnerable to being stolen by other apps, because they are secure. Only your app can be used to utilize links to your validated site.
- Better user experience. The link from the user will always open in your app if installed, or safely in the browser if not.
- Improved SEO. As Universal Links are regular URLs, they exploit SEO benefits and will contribute in enhancing the discoverability of your app.
- Apple’s recommendation. Apple is encouraging developers to UX universal links as the first choice of deep linking, providing improved security and performance.
- Cross-platform compatibility. Universal Links have a clean integration on both iOS and macOS and thus provide a consistent solution.
What’s the best choice?
While custom URL schemes may seem easier to implement, they come with a significant risk: your app’s deep links could be hijacked by anyone. That vulnerability can put not only your users at risk, but also your brand’s reputation.
Universal Links although they require a greater number of steps, provide us with stronger security, robustness, and a more user friendly experience.
Conclusion: Don’t leave your users at risk
If you’re still using custom URL schemes, it’s time to make the switch to Universal Links. The extra level of security is worthwhile the time spent to ensure that your users are safe from malicious redirection and phishing.
Liking this? Follow Raúl Ferrer on Medium (and, better, subscribe me) for more insights and inspiration!
And remember to subscribe my newsletter for insightful content about code, lead and grow.
Code, Lead, Grow | Raúl Ferrer | Substack
How Custom URL Schemes Could Be Putting Your App at Risk was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Raúl Ferrer
Raúl Ferrer | Sciencx (2025-02-14T01:58:18+00:00) How Custom URL Schemes Could Be Putting Your App at Risk. Retrieved from https://www.scien.cx/2025/02/14/how-custom-url-schemes-could-be-putting-your-app-at-risk/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.