Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on Launch in +[QNUserInfo bundle] #458

Open
goodones-mac opened this issue Mar 1, 2024 · 9 comments
Open

Crash on Launch in +[QNUserInfo bundle] #458

goodones-mac opened this issue Mar 1, 2024 · 9 comments

Comments

@goodones-mac
Copy link

goodones-mac commented Mar 1, 2024

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>
@suriksarkisyan
Copy link
Contributor

suriksarkisyan commented Mar 4, 2024

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?

@goodones-mac
Copy link
Author

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.

@suriksarkisyan
Copy link
Contributor

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.

@saagarjha
Copy link

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.

@saagarjha
Copy link

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.

Copy link
Contributor

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.

@github-actions github-actions bot added the awaiting answers There is no activity for a while label Mar 14, 2024
@goodones-mac
Copy link
Author

@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?

@suriksarkisyan
Copy link
Contributor

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!

@github-actions github-actions bot removed the awaiting answers There is no activity for a while label Mar 16, 2024
Copy link
Contributor

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.

@github-actions github-actions bot added the awaiting answers There is no activity for a while label Mar 23, 2024
@SpertsyanKM SpertsyanKM added investigating and removed awaiting answers There is no activity for a while labels Mar 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants