qonversion-ios-sdk
qonversion-ios-sdk copied to clipboard
Crash on Launch in +[QNUserInfo bundle]
Hi your SDK crashes on launch for us because of some issue with NSPredicate? It's happened about 20 times to our users according to sentry, but we haven't seen it in our Xcode builds. Might be a 'security' issue because you query all bundles and apple is getting more restrictive with bundle querying outside of your own app now and _predicateSecurityAction
is in the stack?
The function in question in your library:
+ (nullable NSBundle *)bundle {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"appStoreReceiptURL != nil"];
return [NSBundle.allBundles filteredArrayUsingPredicate:predicate].firstObject;
}
Our code in the stack:
enum QonversionManager {
static func start() {
guard FeatureFlags.Engineering.useQonversionFrozenValue else { return }
let config = Qonversion.Configuration(projectKey: ThirdPartySDKKeys.qonversionSdkKey, launchMode: .analytics)
Qonversion.initWithConfig(config)
QonversionSwift.shared.syncStoreKit2Purchases()
Qonversion.shared().collectAppleSearchAdsAttribution()
}
// ...
}
SIGABRT: expressionValueWithObject:context: > selector
libsystem_kernel 0x1bb28ebbc __pthread_kill
libsystem_pthread 0x1dbd1c850 pthread_kill
libsystem_c 0x18b0a56a8 abort
Foundation 0x1821f66c4 +[_NSPredicateUtilities _predicateSecurityAction]
Foundation 0x18209d6e8 -[NSFunctionExpression expressionValueWithObject:context:]
Foundation 0x182088318 -[NSComparisonPredicate evaluateWithObject:substitutionVariables:]
Foundation 0x1820a4020 _filterObjectsUsingPredicate
Foundation 0x18208d548 -[NSArray(NSPredicateSupport) filteredArrayUsingPredicate:]
GoodOnes 0x1051f1170 +[QNUserInfo bundle] (QNUserInfo.m:99)
GoodOnes 0x1051f0fe8 +[QNUserInfo appStoreReceipt] (QNUserInfo.m:76)
GoodOnes 0x1051f0bdc +[QNUserInfo overallData] (QNUserInfo.m:17)
GoodOnes 0x1051e75e4 -[QNAPIClient launchRequest:] (QNAPIClient.m:133)
GoodOnes 0x1051de9f0 -[QNProductCenterManager launch:] (QNProductCenterManager.m:727)
GoodOnes 0x1051da488 -[QNProductCenterManager launchWithCompletion:] (QNProductCenterManager.m:176)
GoodOnes 0x1051d4ffc -[Qonversion launchWithKey:completion:] (Qonversion.m:96)
GoodOnes 0x1051d4cd4 +[Qonversion initWithConfig:] (Qonversion.m:62)
GoodOnes 0x10512d138 QonversionManager.start (QonversionManager.swift:10)
GoodOnes 0x104e4fb44 QonversionManager.start (<compiler-generated>)
GoodOnes 0x104e4fb44 Logger.initialize (Logger.swift:63)
GoodOnes 0x104dd2460 AppDelegate.application (AppDelegate.swift:26)
GoodOnes 0x104dd2748 AppDelegate.application (<compiler-generated>)
SwiftUI 0x1880b8e70 AppDelegate.application
SwiftUI 0x1880ae2c0 AppDelegate.application
UIKitCore 0x182f6b5cc -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:]
UIKitCore 0x18313fda0 -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:]
UIKitCore 0x1831294c4 -[UIApplication _runWithMainScene:transitionContext:completion:]
UIKitCore 0x182f9731c -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:]
UIKitCore 0x182f967f4 -[UIApplication _compellApplicationLaunchToCompleteUnconditionally]
UIKitCore 0x183147a6c -[UIApplication _run]
UIKitCore 0x182ee0fd0 UIApplicationMain
SwiftUI 0x188199d64 KitRendererCommon
SwiftUI 0x1880e4838 runApp<T>
SwiftUI 0x1880ca1d8 App.main
GoodOnes 0x104ded900 GoodOnesApp.$main (GoodOnesApp.swift)
GoodOnes 0x104ded900 main (GoodOnesApp.swift)
0x106bf84d0 <redacted>
Hi, @goodones-mac Thanks for contacting us. Yes, it looks like some issue inside the Apple NSPredicate logic is unrelated to our code, but I can't be sure because it's almost impossible to reproduce for us. Do you have some clues on how we can reproduce the crash?
No we don't, we just saw it in sentry. 9 users + 20 instances. We are also not a large app so I think it will show up a lot more in bigger apps.
Could you please contact our technical support via Intercom (using our site)? I'll ask you for more details to help us understand the crash.
This is most likely not a bug in your SDK, but a user who is running this on a jailbroken device.
NSPredicate is the frequent target for exploit developers because it provides an easy and reliable way to convert security bugs into code execution. While it is difficult for them to restrict the API for third parties, Apple has started putting security checks in place that tries to block “suspicious” use of NSPredicate in their own apps. Whether these checks are effective or not is a different question (mostly not) but it does mean that constructs like the one in this SDK are flagged by them.
Of course, what Apple does in their own apps is not supposed to have any effect on third-party apps like yours. Unfortunately, the way Apple enables these is by checking the process belongs to a platform application (vaguely, is it Apple signed and shipped with the system). If that is the case this additional validation enables itself. However, this is not the only thing that uses this platform application flag: there are all sorts of privileged and system behaviors that can only be performed by a platform application on iOS.
A jailbreak needs the same level of access, of course. In theory it should grant itself these privileges and run third party apps as-is, but for various reasons most jailbreaks these day are sloppy and mark everything running on the system as a platform application. Usually having more privileges than normal is not a problem because third-party apps do not typically notice. However, Apple tries to enable the security feature on processes they believe are theirs and so when the jailbreak lies about this it ends up turning on for everyone. This is what is crashing your code.
Just to round out the discussion I would also like to say that it’s probably not a good idea to try to detect jailbreak users or similar to work around this. My recommendation would be to avoid using NSPredicate here, which should be fairly straightforward to implement and also more efficient to boot. And if you’re looking to do even better I wouldn’t recommend using +allBundles at all, it’s probably overkill for what you’re doing. If you just need the main app binary, using another method (such as _NSGetExecutablePath) is probably a better bet since it doesn’t need to load all bundles.
This issue is stale because it has been open 7 days with no activity. Remove stale label or comment or this will be closed in 5 days.
@suriksarkisyan this is kind of a short time to auto-close an open issue like this, wondering if we can keep it open so it's tracked properly?
Hi, @goodones-mac I'll let this issue open until we fix it or find the reason for the crash, even if it does not depend on our SDK. I'm not sure, but I'll try to find another solution for our case. Let's keep in touch!
This issue is stale because it has been open 7 days with no activity. Remove stale label or comment or this will be closed in 5 days.
I'm facing this issue July 1st, has it not been resolved any further?
Hi there. We updated our SDK and released 5.12.2 a fix for this issue. As discussed above, this issue is on the Apple side and related to jailbroken devices. I hope this fix will help you never face this issue again. Let's keep in touch!