Fix guide · low · apple_aasa_exposed
Apple App Site Association file exposed
Your /.well-known/apple-app-site-association reveals your iOS team ID, bundle ID, and the deep-link paths your iOS app handles. Required for Universal Links — but the path list can accidentally publish internal routes.
Why it matters
iOS Universal Links require a JSON document at /.well-known/apple-app-site-association (or sometimes the legacy /apple-app-site-association root path) that says "the app identified by team-ID + bundle-ID can handle the following URL paths." Apple's iOS verifies this document before letting the app intercept matching URLs.
The standard shape:
{
"applinks": {
"details": [{
"appID": "ABCDE12345.com.example.MyApp",
"paths": [ "/orders/*", "/account/*", "*" ]
}]
}
}
The "intel value" for an attacker:
- Team ID (
ABCDE12345above) is the public identifier of your Apple Developer account. By itself not a credential, but identifies your organisation across the App Store, TestFlight, and Apple Push Notification service. - Bundle ID reveals your app's reverse-DNS identifier — useful for App Store lookup, identifying your tech stack, and crafting fake-app phishing.
- paths array — this is the spicy bit. The paths are which URL routes the iOS app handles. In real audits we've seen this list reveal:
- Admin-only routes (
/internal/admin/*) that the operator forgot were also iOS-deep-linked. - Staging environments (
/staging/*). - Feature-flag testing endpoints that weren't supposed to be discoverable.
Universal Links work fine with narrow path allowlists. The bug is usually a copy-paste "*" that grants the app every route, including internal ones.
How to fix it
- Narrow the paths list to specifically the routes your iOS app should handle. Avoid
"*"unless every route is truly user-facing. - Audit the existing list for internal/staging/admin paths and remove them.
- Confirm the team ID and bundle ID are the production ones — not staging variants.
- Use the Universal Links validator:
https://search.developer.apple.com/appsearch-validation-tool/?domain=example.comchecks that the file is valid and shows you what iOS sees. - If you have multiple apps (production + staging), serve different AASA files at different subdomains rather than listing all apps in one file.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection