3rd-party closed-source XCFramework security

Hey!

I am developing a macOS application with the help of an external vendor, who is supplying me with a closed-source XCFramework.

In Xcode, when I import their XCFramework bundle, when running the app, or opening a SwiftUI preview, or interacting with the app in any form, I get the familiar dialog:

"[SDK name].framework" Not Opened - Apple could not verify "[SDK name].framework" is free from malware that may harm your Mac or compromise privacy.

(Regardless, the application can run on my machine.)

But indeed, their cross-platform iOS/macOS XCFramework is not notarized at all (using spctl -a -t install), plus the macOS binary embedded is not code signed correctly (using codesign -d). The XCFramework itself is production code signed with a Developer ID certificate, however I believed the above issues to be valid.

Now, I asked the vendor to provide a correctly distributed (so code signed and notarized) framework, however they pointed out that "when I embed and sign the product in my app, it will be re-signed anyways". I understand this is true, but I believe this to be an important security boundary. If I were to re-sign under my name a closed source binary - previously unchecked for malware by Apple Notary Service -, I would put myself up for embedding potentially malicious code in my app, which could only be traced back to me - which would in turn mean a security issue would hinder my reputation here.

Am I being over-protective here, or is this a valid concern? I have no way to see the source code, so I strongly believe this XCFramework should be notarized correctly. I understand that an in-house XCFramework is fine unnotarized, given that I know its origin, but this seems like a unique case where notarization should be enforced from my side on the vendor.

Answered by DTS Engineer in 856845022

You are not being overly paranoid here. Supply chain attacks are real.

I see two parts to this:

  • Making sure you got the right framework.
  • Signing your final product.

I’m gonna tackle them in reverse order.


Imagine an app that, under rare circumstances, erases all the users files. If that happens to a user, they’re not going to be satisfied by the app vendor saying “I got that code from some other vendor.” So, regardless of the legal side of this — and I’m not a lawyer and thus can’t comment on that — it’s clear that, from a reputation standpoint, you are responsible for all the code you ship.

How that’s reflected in code signing depends on your deployment channel:

  • For App Store apps, all code in the app must be signed by your Apple Distribution signing identity. So, yep, you will have to re-sign this framework before submitting it [1].
  • For a directly distributed app, using Developer ID signing, it is possible to include a framework that was Developer ID signed by another developer. Such an app will be accepted by the notary service. However, doing that is bananas from a practical perspective. It greatly complicates your build and distribution process, and can even compromise the runtime security of your app [2].

So, in practice, the only viable option is to re-sign this framework with your signing identity.


However, that’s only the distribution side of this. There’s also the supply chain side. How can you be sure that the framework you’re using is an authenticate framework from that vendor?

Apple introduced a solution for this in Xcode 15. See Verifying the origin of your XCFrameworks and WWDC 2023 Session 10061 Verify app dependencies with digital signatures.

You should encourage your framework vendor to support this.


Finally, the specific error you’re hitting is probably coming up because the framework is quarantined. Assuming you trust the source of the framework, you should remove the quarantine before adding it to your build system.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Apple will then re-sign it again during the distribution process.

[2] Because you’ll have to disable library validation. You can mitigate that on modern systems by using a library constraint, but that’s just doubling down on the pain.

You are not being overly paranoid here. Supply chain attacks are real.

I see two parts to this:

  • Making sure you got the right framework.
  • Signing your final product.

I’m gonna tackle them in reverse order.


Imagine an app that, under rare circumstances, erases all the users files. If that happens to a user, they’re not going to be satisfied by the app vendor saying “I got that code from some other vendor.” So, regardless of the legal side of this — and I’m not a lawyer and thus can’t comment on that — it’s clear that, from a reputation standpoint, you are responsible for all the code you ship.

How that’s reflected in code signing depends on your deployment channel:

  • For App Store apps, all code in the app must be signed by your Apple Distribution signing identity. So, yep, you will have to re-sign this framework before submitting it [1].
  • For a directly distributed app, using Developer ID signing, it is possible to include a framework that was Developer ID signed by another developer. Such an app will be accepted by the notary service. However, doing that is bananas from a practical perspective. It greatly complicates your build and distribution process, and can even compromise the runtime security of your app [2].

So, in practice, the only viable option is to re-sign this framework with your signing identity.


However, that’s only the distribution side of this. There’s also the supply chain side. How can you be sure that the framework you’re using is an authenticate framework from that vendor?

Apple introduced a solution for this in Xcode 15. See Verifying the origin of your XCFrameworks and WWDC 2023 Session 10061 Verify app dependencies with digital signatures.

You should encourage your framework vendor to support this.


Finally, the specific error you’re hitting is probably coming up because the framework is quarantined. Assuming you trust the source of the framework, you should remove the quarantine before adding it to your build system.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Apple will then re-sign it again during the distribution process.

[2] Because you’ll have to disable library validation. You can mitigate that on modern systems by using a library constraint, but that’s just doubling down on the pain.

Thanks Quinn, that's very good to hear.

What about the notarization part? Are my expectations to notarize a closed-source 3rd party xcframework irrealistic?

I think if it were notarized, it wouldn't remain quarantined, because GateKeeper would check its notarization ticket, see it's valid and would remove it automatically from quarantine.

"Trusting" a 3rd-party developer is ultimately trusting their security practices as well - which I would prefer to never do, irrespective of how much I trust the individuals, as that sets me up for external risk exposure, one I wouldn't be able to fix before it hits my machine given that I don't see the framework source code.

E.g. me running the code on my machine happens earlier than my final product notarized or checked by Apple, depending on Developer ID or App Store Distribution - so I would get infected before I would realize what's going on, given that it's closed source.

What about the notarization part?

Standard practice is to sign XCFrameworks with your Apple Distribution signing identity, and such a framework can’t be notarised. AFAIK it’s possible to sign an XCFramework with your Developer ID Application signing identity, and that could be notarised. You can’t staple a ticket to a framework but, assuming you’re online when Gatekeeper first looks at it, it should be able to get the ticket from Apple.

Having said that, if you’re being ‘paranoid’, I think that makes your situation worse, in that it’d allow you to run the code on your development machine without any additional checks. A better option would be:

  1. Get the XCFramework from your vendor.
  2. Run your own static checks.
  3. Then remove quarantine and re-sign it.
  4. Add it to your codebase.

If, in step 2, you want to run Apple’s checks over it, you could re-sign it with your Developer ID Application certificate and notarise it yourself.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

3rd-party closed-source XCFramework security
 
 
Q